«编程之法» 学习
#include <stdio.h>
#include <string.h>
bool StringContain(const char * a, const char * b)
{
if(NULL == a || NULL == b)
{
return false;
}
int aiExists[26] = {0};
int iASize = strlen(a);
int i = 0;
for (i = 0; i < iASize; i++)
{
aiExists[ a[i] - 'a' ] = 1;
}
int iBSize = strlen(b);
for (i = 0; i < iBSize; i++)
{
if(aiExists[ b[i] - 'a' ] != 1)
{
return false;
}
}
return true;
}
void vTest(const char * pcCaseName, const char * a, const char * b, bool bExpectResult)
{
bool bRet = StringContain(a, b);
if(bRet == bExpectResult)
{
printf("%s: pass\n", pcCaseName);
}
else
{
printf("%s: failed\n", pcCaseName);
}
}
void vTest1()
{
vTest("vTest1", "abcd", "ac", true);
}
void vTest2()
{
vTest("vTest2", "abcd", "ae", false);
}
int main()
{
vTest1();
vTest2();
return 0;
}
bool StringContain(const char * a, const char * b)
{
if(NULL == a || NULL == b)
{
return false;
}
int hash = 0;
int iASize = strlen(a);
int i = 0;
for (i = 0; i < iASize; i++)
{
hash |= (1 << (a[i] - 'a'));
}
int iBSize = strlen(b);
for (i = 0; i < iBSize; i++)
{
if((hash & (1 << (b[i] - 'a'))) == 0)
{
return false;
}
}
return true;
}
https://leetcode.com/problems/delete-node-in-a-linked-list/description/
Write a function to delete a node (except the tail) in a singly linked list, given only access to that node.
Supposed the linked list is 1 -> 2 -> 3 -> 4 and you are given the third node with value 3, the linked list should become 1 -> 2 -> 4 after calling your function.
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
void deleteNode(struct ListNode* node) {
if(NULL == node) {
return;
}
struct ListNode * pNextNode = node->next;
node->val = pNextNode->val;
node->next = pNextNode->next;
free(pNextNode);
}
这样删除节点是有问题的,如果这个节点是最后节点。
就算删除了,那这个节点的前一个节点的next指针也没有置为NULL。
几个常见的运算符的优先级
() > +-(一元运算符) > */ > +-(二元运算符) > =
括号 正负 乘除 加减 等号
sizeof 运算符是以字节为单位返回其操作数的大小。
sizeof不是函数
typedef double real;
使real成为double的别名。
取模运算符: % 只用于整数。
不要对浮点数使用该运算符,那将是无效的。
a % b = a - (a/b)*b 这个式子只要a和b是整数就成立,不论正负。
例子:
11 % 5 = 11 - (11/5)*5 = 1
11 % -1 = 11 - (11/-2)*(-2) = 1
-11 % -5 = -11 - (-11/-5)*(-5) = -1
-11 % 5 = -11 - (-11/5)*5 = -1
++ -- 增量运算符,减量运算符
通常会产生更高效的机器语言代码。
x*y++ 代表 (x)*(y++)
增量和减量运算符有很高的优先级,只有圆括号比他们的优先级高。
增量和减量运算符只能对变量起作用, 而 (x*y) 不是一个变量。
n++ 先使用n,然后将它的值增加。
++n 先将n的值增加,然后再使用它。
如果一个变量出现在同一个函数的多个参数中时,不要将增量或减量运算符用于它上面。
当一个变量多次出现在一个表达式里时,不要将增量或减量运算符遇于它上面。
顺序点
定义:一个顺序点是程序执行中的一点:在该点处,所有的副作用都在进入下一步前被计算。
例如:
语句里的分号标志了一个顺序点。
任何一个完整的表达式的结束也是一个顺序点。
一个完整的表达式:它不是一个更大的表达式的子表达式。
例子1:
while (guests++ < 10)
printf("%d \n", guests);
因为 guests++ < 10 是一个完整的表达式,C语言保证副作用进入 printf 之前发生。
例子2:
y = (4 + x++) + (6 + x++);
表达式 4 + x++ 不是一个完整的表达式,所以C语言不保证在计算子表达式 4 + x++ 之后立即增加X。
完整表达式是整个赋值语句,并且分号标记了顺序点,所以C语言保证在进入后续语句前X将被增加两次。
通常大部分情况下,32位下的程序都能够正常的运行在64位系统中。
但是如果32位的程序需要修改调用一些系统底层的API,比如修改系统的IP地址, 禁用,启用网卡,这个时候32位的程序就无法正常使用。
将调用底层API的部分单独编一个 64 位的 api.exe,然后用32位的程序调用这个 api.exe。
#include <Windows.h>
#include <strsafe.h>
void ErrorExit()
{
void * lpMsgBuf;
FormatMessageA(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(char *)&lpMsgBuf,
0,
NULL);
printf("**************************** error = %s\n", lpMsgBuf);
LocalFree(lpMsgBuf);
}
int main()
{
if( ! GetProcessId(NULL) )
{
ErrorExit();
}
return 0;
}
输出汇编文件 项目->属性->配置属性->C/C++->输出文件->右边内容项: 汇编输出 中选择 带源代码的程序集(/FAs), 这样,会在项目目录下生成后缀为*.asm的文件. (在VC6.0中的方法为:project settings: ->C++->category == Listing files -> listing file type == Assembly with source code)
使用反汇编方式 在断点调试的时候, 点击”调试” ->”窗口” -> “反汇编” (VC6.0下为: 在进行断点调试时,点击”查看”->”调试窗口”->Disassably”, 即可查看到反汇编结果)
#include <stdio.h>
int main()
{
printf("hello world\n");
int i;
i= 0;
printf("i = %d\n", i);
i++;
/*
mov eax, DWORD PTR _i$[ebp]
add eax, 1
mov DWORD PTR _i$[ebp], eax
*/
//++i;
/*
mov eax, DWORD PTR _i$[ebp]
add eax, 1
mov DWORD PTR _i$[ebp], eax
*/
//i = 1;
//mov DWORD PTR _i$[ebp], 1
//i = i + 1;
/*
mov eax, DWORD PTR _i$[ebp]
add eax, 1
mov DWORD PTR _i$[ebp], eax
*/
return 0;
}