C fscanf读取指向字符数组的指针

时间:2016-10-13 09:46:18

标签: c scanf

我正在尝试使用fscanf将文件中的行读入指向字符数组的指针。我打印时遇到分段错误。我究竟做错了什么?我应该使用fscanf以外的功能吗?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "stack.h"

#define MAXSTACK 100
#define MAXLENGHT 100

void main(int argc, char * argv[]){

  char *filename;
  FILE *fp;
  char *lines[MAXSTACK];
  char * command;
  int top = 0;
  int numlines = 0;

  if(argc < 3){

    fprintf(stderr,"error: Not enough arguments provided\n");
    exit(1);
  }

  filename = argv[1];
  command = argv[2];

  if ( (fp = fopen(filename,"r")) == NULL ){

    fprintf(stderr,"error: Cannot open file %s\n",filename);
    exit(1);
  }
  else{

    for(int i = 0; i < 3; i++){

        fscanf(fp,"%s",lines[i]);
    //    printf("%s\n",lines[i]);
    }

    char **ptr2 = lines;
    for (int i = 0; i < 2; i++){

         printf("%s\n", ptr2[i]);
    }

    if (strcmp(command,"pop")==0){

      //pop(lines);
     }else if (strcmp(command,"print_top")==0){
      //print_top();

    }else if(strcmp(command,"swap_top")==0){

    }
   }
} 

2 个答案:

答案 0 :(得分:2)

您可能希望使用fgets读取行:

/* Read a single line into a temporary buffer */
char lineBuffer[MAX_LINE_LENGTH];
while (fgets(lineBuffer, sizeof(lineBuffer), fp) != NULL) {
    /* Process the read line */
}

在临时缓冲区中读取一行后,您可以将读取的字符串深度复制到使用malloc在堆上分配的某个内存中(或者您可以使用strdup),然后你可以将指向该内存的指针存储到lines数组中:

 /* Inside the body of the while loop */

 /* 
  * Deep copy current line into the string pointer array.
  * strdup = malloc + strcpy
  * Note that free is required to release memory!
  */
 lines[currLineIndex] = strdup(lineBuffer);

 currLineIndex++;

请注意,当您编写如下代码时:

char *lines[MAXSTACK];

您正在堆栈上分配一个MAXSTACK项数组,每个项目都是char*指针。但是你必须给那些指针赋予一些有意义的值(例如:从堆中分配一些内存并指向那个内存)。

当然,完成后,您必须扫描整个数组并在每个元素指针上调用free以避免内存泄漏。

此外,一个好的编码实践是在使用它之前清除数组中的指针,例如:

memset(lines, 0, sizeof(lines));

答案 1 :(得分:1)

fscanf("%s", lines[i])将读取一系列非空白字符(注意,而不是整行)到lines[i]指向的内存中。问题是,您没有将lines[i]设置为指向任何内存,这就是您获得segfault的原因,您要求将一系列字符复制到某个未定义的位置。

如果用一个字符数组char *lines[MAXSTACK];的声明替换你的字符指针数组char lines[MAXLENGTH][MAXSTACK]的声明,那么lines[i]将是{{1}的数组MAXLENGTH能够复制到没有seg faulting的字符。

问题仍然存在,如果字符串fscanf尝试读取的内容超过fscanf("%s", lines[i])会发生什么?答案是更多的字符将被读取,而不是适合MAXLENGTH数组,你得到的是所谓的缓冲区溢出。为防止出现这种情况,您可以将lines[MAXLENGTH]从字符串中读取的最大字符数限制为100,例如,fscanf