所以,这是我第一次在这里发帖,我会尝试尽可能具体。 我必须为我的学校制作一个节目:
首先编写一个获取字符并返回的函数:
然后,使用您的函数,创建一个程序,使其成为一个字符串,并在该函数更改后重新打印它。在用户输入' QUIT'之前,它应该继续询问新的字符串,在这种情况下,它将打印“Bye!”#39;然后退出。
这是我的代码:
#include <stdio.h>
#include <stdlib.h>
char fnChange(char c)
{
if (c > 'a'-1 && c < 'z'+1)
c = c - 32;
else if (c > '0'-1 && c < '9'+1)
c = '\\' ;
else if ( c > 'A'-1 && c < 'Z'+1)
c = c;
else
c = '*';
return c;
}
int main()
{
int i, refPoint;
char *str = (char*)malloc(10);
//without the next one, the program crashes after 3 repeats.
refPoint = str;
while (1==1) {
printf("Give a string: ");
str = refPoint;//same as the comment above.
free(str);
scanf("%s",str);
if (*str == 'Q' && *(str+1) == 'U' && *(str+2) == 'I' && *(str+3) == 'T') {
// why won't if (str == 'QUIT') work?
free(str);
printf("Bye!"); //after printing "Bye!", it crashes.
system("pause"); //it also crashes if i terminate with ctrl+c.
exit(EXIT_SUCCESS); //or just closing it with [x].
}
printf("The string becomes: ");
while (*str != '\0') {
putchar(fnChange(*str));
str++;
}
printf("\n");
}
}
答案 0 :(得分:5)
free(str);
scanf("%s",str);
Big no-no,在释放后不允许使用动态分配的内存。最重要的是,你可以在循环中再次释放 。
这样做是未定义的行为。这几乎可以肯定是导致事故发生的原因。
其他几个问题。您可以使用<=
代替<
来提高代码的可读性,例如:
if ((c >= 'a') && (c <= 'z')) ...
使用像32
这样的 magic 数字几乎总是一个坏主意。如果您使用字母连续的编码(例如ASCII),则可以执行以下操作:
c = c - 'A' + 'a';
将大写变为小写。
)因为字母不保证是连续的。
表达式toupper()
不符合您的想法,因为tolower()
不是字符串。相反,它是一个多字节字符文字。但是,即使isupper()
也不会按照您的想法行事,因为在C中比较字符串的正确方法是:
islower()
答案 1 :(得分:4)
您的代码中有多个undefined behavior个案例。
首先,您指定一个指向整数变量的指针。那些并不是真正兼容的(例如,如果int
的大小是32位且指针的大小是64位,那么会发生什么。)
然后在使用之前释放已分配的指针,从而写入未分配的内存。
稍后再次在同一指针上调用free
。
答案 2 :(得分:1)
这可能导致崩溃的原因有很多。按照您的代码顺序,或多或少:
你free
str然后对其进行扫描。一旦释放了内存,它就不再可用了。
然后是scanf:scanf("%s", str)
。一旦有人在控制台输入一个包含10个或更多字符的字符串,就会输入未定义行为的领域,因为内存将被覆盖。
将str
分配给refpoint
,反之亦然,应该为您提供大量编译器警告。您的一个变量是int
,另一个是char *
。在某些体系结构中,指针不适合int
,并且一旦使用它,程序就会崩溃。
您的while循环递增str
。如果没有来自refpoint
的(危险)副本,您最终会尝试释放一个不是malloc
结果的指针。这是未定义的行为,可能会崩溃。
顺便说一下:
请不要投射malloc
的结果。它返回一个void *,在C中你可以为任何东西分配void *
,不必要的强制转换会降低代码的可读性。施法意味着你做了一些不寻常的事情,并且这项任务不是。
你不能做str == 'QUIT
'因为C编译器会比较字符串的地址 - 嗯,键入'QUIT'的效果是编译器相关的。它可能会将它与'Q'的字符值进行比较。即使使用str == "QUIT"
,它也会将指针str
的值(即malloc
返回的地址)与字符串“QUIT”的地址进行比较,该字符串将位于链接器的任何位置旨在存储它。 C不进行字符串比较,你必须使用strcmp
。