C编程语言中的指针数组(第5.6章)示例

时间:2014-03-05 09:21:24

标签: c arrays pointers

我的理解是,一旦指针初始化为字符串常量,就不能修改字符串。我尝试过执行修改,程序崩溃了。

这一理论在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。谢谢。

5 个答案:

答案 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 */