我的理解是,一旦指针初始化为字符串常量,就不能修改字符串。我尝试过执行修改,程序崩溃了。
这一理论在Brian W. Kernighan和Dennis M. Ritchie的C编程语言第5.5章“字符指针和函数”中给出。
但是有一个在数组中存储指针的例子(第5.6章),其中指针的内容被修改。该计划如下:
#include <stdio.h>
#include <string.h>
#define MAXLINES 5000 /* max #lines to be sorted */
#define MAXLEN 1000
char *lineptr[MAXLINES]; /* pointers to text lines */
char *alloc(int);
int readlines(char *lineptr[], int nlines);
int getline(char *, int);
void writelines(char *lineptr[], int nlines);
main()
{
int nlines; /* number of input lines read */
if ((nlines = readlines(lineptr, MAXLINES)) >= 0) {
writelines(lineptr, nlines);
return 0;
} else {
printf("error: input too big to sort\n");
return 1;
}
}
/* readlines: read input lines */
int readlines(char *lineptr[], int maxlines)
{
int len, nlines;
char *p, line[MAXLEN];
nlines = 0;
while ((len = getline(line, MAXLEN)) > 0)
if (nlines >= maxlines)
return -1;
else {
line[len-1] = '\0'; /* delete newline */
strcpy(p, line);
lineptr[nlines++] = p;
}
return nlines;
}
/* writelines: write output lines */
void writelines(char *lineptr[], int nlines)
{
int i;
for (i = 0; i < nlines; i++)
printf("%s\n", lineptr[i]);
}
int getline(char s[],int lim)
{
int c, i;
for (i=0; i < lim-1 && (c=getchar())!=EOF && c!='\n'; ++i)
s[i] = c;
if (c == '\n') {
s[i] = c;
++i;
}
s[i] = '\0';
return i;
}
程序在编译时不会显示任何警告或错误,但在输入第一行后会崩溃。
请您确认这是否是由于修改了初始化为指针的字符串常量?有问题的指针是@第28行“char * p”,并在第35行执行了strcpy。谢谢。
答案 0 :(得分:3)
它崩溃了
strcpy(p, line);
因为p
没有指向已分配的内存;
你应该添加这样的东西
p = (char*)malloc(sizeof(char)* MAXLEN);
更新:
也在这里
for (i=0; i < lim-1 && (c=getchar())!=EOF && c!='\n'; ++i)
如果长度为MAXLEN的字符串以'\ n'结尾,则i
可能会达到lim
值。然后
if (c == '\n') {
s[i] = c;
++i;
}
你会将'\ n'分配给s [MAXLEN](lim = MAXLEN),你将超越界限。 (索引应介于0和MAXLEN - 1
之间。
我建议改变
for (i=0; i < lim-1 && (c=getchar())!=EOF && c!='\n'; ++i)
到
for (i=0; i < lim-2 && (c=getchar())!=EOF && c!='\n'; ++i)
答案 1 :(得分:1)
您正在写一个单元化指针。
您的声明
char *p, line[MAXLEN];
然后你做
strcpy(p, line); // here p points to invalid memory and therefore the program crashes
你应该为p分配内存,如下所示
else {
line[len-1] = '\0'; /* delete newline */
p = (char*)malloc(len) ; // <<<<<<<<<<-- add this line
strcpy(p, line);
lineptr[nlines++] = p;
BTW:在没有警告的情况下编译的程序确实意味着它不会崩溃。编译带有警告的的程序可能会完美运行。
答案 2 :(得分:1)
指针指向CAN的存储器的内容可被修改 (否则一开始就没用) 你的意思是像
char *p = "hello";
这是一种特殊情况,你不允许修改你好,但是......
你的问题:你没有指针的内容,即。没有指定的记忆。
阅读关于malloc和free。
答案 3 :(得分:1)
您遇到的问题是char *p
中的readlines()
未定义。正如您在当前的代码示例中所写的那样,p
是一个随机内存块开头的地址,其大小为单个char
。在K&amp; R(第二版)示例代码中,while
中的readlines()
循环实际上如下所示:
while((len = getline(line, MAXLEN)) > 0) {
if (nlines >= maxlines || (p = alloc(len)) == NULL){
return -1;
}
else {
line[len-1] = '\0';
strcpy(p, line); //now this should work
lineptr[nlines++] = p;
}
}
使用alloc()
,作者在前面第5章中定义的或,使用malloc()
中定义的更合理的<stdlib.h>
,然后,您可以将p
定义为既有意义又可以安全使用/操作的内容。
答案 4 :(得分:1)
我知道这是一个挖掘,它可能无法解决您的问题,但这里有一个错误:
line[len - 1] = '\0'; /* delete newline */
在代码结束后,它将您指向第1.9章中的getline()
,其中包含以下内容
for(...; ... s[i] != '\n'; ...)
s[i] = '\0';
getline()
使用s[i] = '\0'
处理换行符,因此根本不需要line[len - 1] = '\0'; /* delete newline */
。