2017-10-08 72 views
0

我正在开发一个C函数,用于对给定键周围的文本进行排序。 比方说,你有以下文件:C排序程序中的分段错误

this line is first 
but this line is second 
finally there is this line 

如果你运行该程序,并给它这个文件作为输入,它应该打印:

but this line is second 
finally there is this line 
this line is first 

因为不过是字母前最后是在此之前。

但是,如果您传递一个标志来对不同的键进行排序,则会得到不同的输出。例如,如果你调用fastsort -2这个文件,你应该得到:

this line is first 
finally there is this line 
but this line is second 

,因为全系标配在此之前有到来之前。是的,我假设-2代表每行中的第二个单词(与大多数人一样,除了计算机科学家总是希望从0开始)。此外,如果指定的键不存在于输入文件的特定行上,我应该只使用该行的最后一个词作为键。例如,如果用户想要对第4个单词(-4)进行排序,并且排序遇到类似此行的线(采样线),则排序应使用单词对该行进行排序。

我的问题来自于最后一个假设,我使用strtok()来提取键给出的单词,但是如果键大于该行中的单词数,则会出现分段错误。这是函数的主体;

typedef struct { 
    char word[128]; 
    int index; 
} wordIndex; 

char** fastsort(char** text, int word){ 

char** sortedText; 
char* LineAux; 
int i; 
wordIndex tokenLines[numLines]; 

for(i=0; i<numLines; i++){ 
    char* token; 
    int j = 0; //counter 

    LineAux = (char*) malloc(MAX_LENGTH*sizeof(char)); //MAX_LENGTH = 128 
    if (LineAux==NULL){ 
     fprintf(stderr,"Error, malloc failed"); 
     exit(1); 
    } 

    strcpy(LineAux,text[i]); 

    token = strtok(LineAux, " \n"); 
    j++; 

    if(token == NULL){ //if blank line 
     token=" "; 

    } else { 

     while(token != NULL){ //segmentation fault 
      if(j == word){ 
       break; 
      } 
      token = strtok(NULL, " \n"); 
      j++; 

     } 
    } 

    strcpy(tokenLines[i].word,token); 
    tokenLines[i].index=i; 
    free(LineAux); //free Aux string 
    printf("token: %s Line: %d \n",tokenLines[i].word, tokenLines[i].index); 
} 

qsort(tokenLines,numLines,sizeof(wordIndex),compareTo); //sorting tokens 

sortedText = (char**) malloc(numLines*sizeof(char*)); 
if (sortedText==NULL){ 
    fprintf(stderr,"Error, malloc failed"); 
    exit(1); 
} 


//reordering text 
int n; 
for (n=0; n<numLines; n++){ 
    int index; 

    sortedText[n]=(char*) malloc(MAX_LENGHT*sizeof(char)); 

    if (sortedText[n]==NULL){ 
     fprintf(stderr,"Error, malloc failed"); 
     exit(1); 
    } 

    index = tokenLines[n].index; 
    strcpy(sortedText[n],text[index]); 

} 


return sortedText; 

}

分段错误出现的while循环中。 希望你能帮忙,谢谢你提前。

+0

'text [i]'可以长于127个字符加终止字节吗?因为如果可以的话,你的'strcpy'会超出'LineAux'的范围。 'text [index]'进一步向下。 –

+0

@CharlesSrstka不,我有另一个功能(从文件中提取文本),防止行超过127个字符(+终止),所以它永远不会比这更长 – Setekorrales

+0

什么是'wordIndex'?某种结构我采取它? –

回答

1

我在我的机器上运行了上面的代码。它的工作,一个警告; word是1索引,而不是像你所期望的0,因为j在与任何事物比较之前都会增加。所以,如果你输入0,你自然不会,如果你想用的第一个词进行排序,这条线是永远不会是真实的:

if(j == word){ 

因此,while循环继续,直到令牌NULL。然后,在循环后,您strcpy崩溃,因为它试图尊重你传递给它的空指针:

strcpy(tokenLines[i].word,token); // don't NULL me bro! 

这是你的崩溃的根源。为了解决这个问题,我会想办法让两个转变:

  1. 得到循环之前摆脱j++的。让索引开始于0,因为这通常是在C中完成的以及函数的用户通常期望的内容。

  2. 循环结束后,测试token以查看它是否为NULL。如果是,优雅地退出该功能,可能会向用户返回某种错误。如果有人输入一个无效的单词编号就会崩溃,这是糟糕的UI。

0

Allrigth,我有解决办法;

问题是while循环内部指令的顺序。

这里是工作的解决方案:

/** 
* Function that sorts text by a given key 
* @param text: array of strings which is going to be sorted 
* @param word: key where the sort starts 
* @return sorted text 
*/ 
char** fastsort(char** text, int word){ 

    char** sortedText; 
    char* LineAux; 
    int i; 
    wordIndex tokenLines[numLines]; 

    for(i=0; i<numLines; i++){ 
     char* token; 
     int j = 0; //counter 

     LineAux = (char*) malloc(MAX_LENGHT*sizeof(char)); 
     if (LineAux==NULL){ 
      fprintf(stderr,"Error, malloc failed"); 
      exit(1); 
     } 

     strcpy(LineAux,text[i]); 

     token = strtok(LineAux, " \n"); 
     j++; 

     if(token == NULL){ //if blank line 
      token=" "; 

     } else { 

      while(token != NULL){ //segmentation fault 
       strcpy(tokenLines[i].word,token); 
       if(j == word){ 
        break; 
       } 

       token = strtok(NULL, " \n"); 
       j++; 

      } 
     } 

     tokenLines[i].index=i; 
     free(LineAux); //free Aux string 
    } 

正如你所看到的,变化不是很有效,但它的工作,现在,如果你有一个替代的解决方案,我会很乐意去尝试。