2010-03-24 37 views
4

在我结束第一次循环后,我一直在收集seg错误,对于我的生活,我不知道为什么。 我正在扫描的文件只有18行中的18个字符串。 我认为这个问题是我将malloc称为picks的双指针,但我不知道为什么。 我只是想扫描长度小于15个字符的字符串,所以我没有看到问题。有人可以请帮助。有人能告诉我为什么我在这个简单的C程序中发生seg错误吗?

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#define MAX_LENGTH 100 

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

    char* string = malloc(15*sizeof(char)); 
    char** picks = malloc(15*sizeof(char*)); 
    FILE* pick_file = fopen(argv[l], "r"); 
    int num_picks; 


    for(num_picks=0 ; fgets(string, MAX_LENGTH, pick_file) != NULL ; num_picks++) 
    { 
     scanf("%s", picks+num_picks); 
    } 
    //this is where i seg fault 
    int x; 
    for(x=0; x<num_picks;x++) 
    printf("s\n", picks+x); 
} 
+0

当您访问您无权访问的内存时,总会出现分段错误。在大多数情况下,这意味着你正在访问超出其范围的数组[或未分配的对象/未定义的变量]。请记住,下一次你得到一个 - 这种消除搜索,特别是这样一个简单的程序。 – 2010-03-23 07:59:43

回答

5
  1. string只得到分配足够的内存来存储一个字符(sizeof(char))。如果要存储更多字符,则需要将sizeof(char)乘以要存储的字符串的大小,并在最后加上一个空字符。

  2. 相反的:

    char** picks = malloc(15*sizeof(char)); 
    

    你想这样做:

    char** picks = malloc(15*sizeof(char*)); 
    

    picks阵列的每个元素都必须大到足以容纳一个指针。

+1

...和挑选元素需要分配以及。 – philant 2010-03-23 08:03:14

+0

...并且至少需要其中的18个,而不是15个。 – caf 2010-03-23 14:05:17

+0

对于(1),请注意一个单字符的字符串足以存储零字节终止符,因此这足够长,以便空字符串没有别的。 – 2010-03-23 14:07:22

3

首先,在C字符串中存储为byte(char)数组,并且必须进行分配。在这种情况下,用来读取他文件中的字符串应分配MAX_LENGTH + 1(+1为一个字符串结束,\ 0)字符:

char* string = malloc((MAX_LENGTH+1) * sizeof(char)); 

这将最大长度的字符串分配足够的内存:最长长度。

另一个问题是,指针char **picks的阵列未分配给存储18串你希望阅读:

它必须被分配给15个字符指针(字符*),这也有在第一个循环中分配。

int main(int argc,char *argv[]) 
{ 
    ... 
    char* string = malloc((MAX_LENGTH+1) * sizeof(char)); 
    char** picks = malloc(15*sizeof(char *)); 
    FILE* pick_file = fopen(argv[l], "r"); 
    int num_picks; 

    for(num_picks=0 ; fgets(string, MAX_LENGTH, pick_file) != NULL ; num_picks++) 
    { 
     printf("pick a/an %s ", string); 
     //--- allocate the char array to store the current string 
     picks[num_picks] = malloc (15 * sizeof(char)); 
     sscanf(string, "%s", picks[num_picks]); 
    } 

    for(int x=0; x<num_picks;x++) 
    printf("%s\n", picks[x]); 
} 

您还必须测试的malloc()的返回值,并且你可能想测试,如果文件内容真的是如预期,不包含更多的线路,或超过15个字符长行。


另外scanf()的读取标准输入,我的sscanf()代替它,而在第二个printf加入缺少的 '%' 符号()。

0

是因为在该行:
for(num_picks=0 ; fgets(string, MAX_LENGTH, pick_file) != NULL ; num_picks++)
MAX_LENGTH是100,但你读到变量string,这只能承载一个个性?

1
  • 位置指向string只分配空间一个字符,但你尝试读取多达MAX_LENGTH字符进去;
  • picks指向的位置只分配了空间,用于指针15 char *,但您显然希望存储指向18个字符串的指针;
  • picks指向的位置已分配但从未初始化。您需要让这15(或18)个指针实际指向自己的东西,然后再将它们交给scanf

在这种情况下,实际上不需要动态分配的话 - 你可以做你想要使用数组什么:

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

#define MAX_LENGTH 100 
#define MAX_LINES 18 

int main(int argc, char *argv[]) 
{ 
    char string[MAX_LENGTH]; 
    char picks[MAX_LINES][MAX_LENGTH]; 
    FILE *pick_file = NULL; 
    int num_picks; 

    if (argc > 1) 
     pick_file = fopen(argv[1], "r"); 

    if (pick_file == NULL) 
     return 1; 

    for (num_picks = 0; num_picks < MAX_LINES && fgets(string, MAX_LENGTH, pick_file) != NULL; num_picks++) 
    { 
     printf("pick a/an %s ", string); 
     scanf("%s", picks[num_picks]); 
    } 

    int x; 
    for (x = 0; x < num_picks; x++) 
     printf("%s\n", picks[x]); 

    return 0; 
} 
0

您分配十五char*一个数组picks

char** picks = malloc(15*sizeof(char*)); 

现在picks有足够的空间来存储十五个char*,但你从来没有实际上把任何指针指向内存的指针应该包含读字符。

您需要为这些字符串分配内存,这些字符串将与scanf一起读取。目前,scanf只是将数据写入指向picks(尚未初始化为指向任何有用位置的指针)指向的任何位置。

0

你在这里遇到seg错误。

scanf("%s", picks+num_picks);

,而不是这样做,

for(num_picks=0 ; fgets(string, MAX_LENGTH, pick_file) != NULL ; num_picks++) 
{ 
    pics[num_picks] = (char*)malloc(100); 
    scanf("%s", picks+num_picks); 
} 

的问题是,U分配**pics持有15串,但你读的字符串,而不对这些字符串分配的空间。确保你总是读入分配的指针。

9

picks是一个指针指针:这意味着它指向的东西都是指针。

当你这样做:

char** picks = malloc(15*sizeof(char*)); 

您正在picks点到15个球块 - 这是很好的,只要它去(虽然,因为你想在线看,你真的需要18个而不是15个)。这意味着,picks点的变量在内存中像这样的块:

| picks (char **) | --------> | picks[0] (char *) | ----> ? 
           | picks[1] (char *) | ----> ? 
           | picks[2] (char *) | ----> ? 
           | ...    | 
           | picks[14] (char *) | ----> ? 

正如你可以看到,这15个char *指针现在unintialised - 他们不指向任何东西。直到你分配一些内存为那些你不能开始使用它们,太 - 你需要做这样的事情:

int i; 
for (i = 0; i < 15; i++) 
{ 
    picks[i] = malloc(15); 
} 

现在,在此之后,内存布局是这样的:

| picks (char **) | --------> | picks[0] (char *) | ----> | picks[0][0] (char) | 
                  | picks[0][1] (char) | 
                  | ...     | 
                  | picks[0][14] (char) | 

           | picks[1] (char *) | ----> | picks[1][0] (char) | 
                  | ...     | 

           | ...    | 

...你现在有地方存储所有你想阅读的字符。

+4

我被ascii代表性的诗意之美所感动,几乎到了哭泣的地步......对于喜悦来说,这可能是这个问题的最后一个化身:) – 2010-03-24 05:19:24

+1

同意......我回答了一些事情,但我很谦卑什么“加载新答案”橙色酒吧带到我眼前! – Newtopian 2010-03-24 05:23:53

相关问题