嗨,我写了这段代码,它有效,但最终,"程序已停止工作">
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
#include <string.h>
void main()
{
char *s;
s=(char*)malloc(sizeof(char));
printf("Enter a string:n");
gets(s);
while (*s)
{
if (*s>= 65 && *s<=90)
printf("%c",*s+32);
else if(*s>=97 && *s<=122)
printf("%c",*s-32);
else
printf("%c",*s);
*s++;
}
free(s);
}
该代码不起作用,实际上它具有未定义的行为。
这:
s = (char *) malloc(sizeof(char));
分配 1 字节的存储,然后将字符串扫描到其中,因此很可能导致缓冲区溢出。缓冲区只能保存单个字符串,即末尾终止符字符之前的 0 个字符的字符串。
你的意思是:
s = malloc(128);
或类似的东西。
无需强制转换,并且sizeof (char)
始终为 1,因此不会添加任何内容。
此外,作为更多的代码审查,代码中的幻数通常被认为是一个坏主意,而是写:
if (*s >= 'A' && *s <= 'Z')
甚至更好
if (isupper((unsigned int) *s))
不对 ASCII 上的 depdency 进行硬编码。
更新哦,正如评论中指出的那样,您不能更改s
的值,然后将更改的值传递给free()
,这也是未定义的行为。传递给free()
的地址必须与您从malloc()
那里取回的地址相同。
使用单独的变量进行迭代:
char *p = s;
并且只free()
原始s
.
首先,通过s=(char*)malloc(sizeof(char));
,您只为缓冲区分配了 1 字节的内存。分配足够的内存来存储输入。还要避免对结果进行类型转换malloc()
。更好的版本看起来像
s = malloc(MAX * sizeof(*s));/* MAX is num of bytes you need to define */
其次,不要使用gets()
而使用fgets()
。阅读man 3 gets
或检查 https://linux.die.net/man/3/gets
最后使用int main(void) { }
而不仅仅是main(){ }
更重要的是,当您在那个时候执行free(s)
时,s
不会指向由于s++
而先前分配给它的内存,因此可能会导致错误,例如
free(): 无效指针:
因此,在迭代时不要更改s
使用s[row]
或者您可以将s
分配给其他指针,然后您可以执行free(s)
。
完整代码
int main() {
char *s = NULL;
int size = MAX*sizeof(*s);/*define MAX value, it is no of bytes need*/
s = malloc(size);/* this is generic
sizeof(*s) works for any data type */
printf("Enter a string:n");
fgets(s,size,stdin);/* use fgets() instead of gets() */
int row = 0;
while (s[row]!=' ') {
if ( *(s+row) >= 65 && *(s+row) <= 90)
printf("%c",*(s+row) + 32);
else if( *(s+row) >=97 && *(s+row) <= 122)
printf("%c",*(s+row) - 32);
else
printf("%c",*(s+row));
row++;
}
free(s);/* s still points to same location */
return 0;
}
您也可以使用isupper()
而不是比较每个字符 ASCII 值。
这是错误的。
s = (char*)malloc(sizeof(char));
printf("Enter a string:n");
gets(s);
s = (char*)malloc(sizeof(char));
分配 1 个字节的内存。然后用gets(s);
你得到一个字符串,它将是未定义的行为。
您必须将其更改为
s = malloc(MAX_LENGTH * sizeof(char)); //MAX_LENGTH is user defined
此外,您必须检查malloc()
是否返回了任何内容。如果它返回NULL
则意味着没有分配内存,所有现有程序都将调用未定义的行为。 此外,无需强制转换malloc
结果,因此要进一步改进代码,您需要将其更改为,
s = malloc(MAX_LENGTH * sizeof(char));
if(s == NULL)
{
// Add error handling here
}
也
void main()
不再是标准,请参阅这篇文章,其中解释了原因。如果您想知道 C11 标准对此有何规定,请参阅此处的标准: 第 5.1.2.2.1 节 程序启动
所以把它改成,
int main(void)
您应确保仅在分配free(s);
时才调用它。正如下面的评论之一正确指出free(NULL);
不是问题,但它也没有影响,所以为什么要称呼它。
再次指出s
NULL
,但它与这段代码无关。