从strncpy()函数中获取奇怪字符

从strncpy()函数中获取奇怪字符,c,arrays,string,c-strings,C,Arrays,String,C Strings,我应该从一个文件中加载一个名称列表,然后在第二个文件中找到这些名称,并将它们加载到一个包含其他数据的结构中(为了简单起见,我将把它们加载到另一个名为“test”的数组中) 第一部分很好,我正在打开一个文件并将所有名称加载到名为namesArr的二维数组中。 第二部分是出现意外字符的地方,我不明白为什么。下面是函数的代码: void loadStructure(void){ char line[MAX_PL_LENGTH], *found; int i, j=0; char

我应该从一个文件中加载一个名称列表,然后在第二个文件中找到这些名称,并将它们加载到一个包含其他数据的结构中(为了简单起见,我将把它们加载到另一个名为“test”的数组中)

第一部分很好,我正在打开一个文件并将所有名称加载到名为namesArr的二维数组中。 第二部分是出现意外字符的地方,我不明白为什么。下面是函数的代码:

void loadStructure(void){
    char line[MAX_PL_LENGTH], *found;
    int i, j=0;
    char test[20][20];

    FILE *plotPtr=fopen(PLOT_FILE_PATH, "r");
    if (plotPtr==NULL){perror("Error 05:\nError opening a file in loadStructure function. Check the file path"); exit(-5);}
    while(fgets(line, MAX_PL_LENGTH, plotPtr)!=NULL){                   // This will load each line from a file to an array "line" until it reaches the end of file.
        for(i=0; i<numOfNames; i++){                                    // Looping through the "namesArr" array, which contains the list of 20 character names.
            if((found=strstr(line, namesArr[i]))!=NULL){                // I use strstr() to find if any of those names appear in the particular line.
                printf("** %s", found);                                 // Used of debugging.
                strncpy(test[j], found, strlen(namesArr[i])); j++;      // Copying the newly found name to test[j] (copying only the name, by defining it's length, which is calculated by strlen function).
            }
        }
    }
    fclose(plotPtr);
    printf("%s\n", test[0]);
    printf("%s\n", test[1]);
    printf("%s\n", test[2]);
}

问题是,为什么我会有这样的角色╕&q“和”ⁿ  └" 在新创建的数组中?还有,有没有其他更有效的方法来实现我正在尝试做的事情?

问题是,如果指定的长度小于源字符串,则
strncpy
不会在目标数组中存储空值(这里总是这样)因此
测试
数组中发生的任何垃圾都将保留在那里

您可以通过将
test
数组归零来解决此特定问题,方法是:

char test[20][20] = { { 0 } };
或者当您使用它时:

memset(test[j], 0, 20);
strncpy(test[j], found, strlen(namesArr[i]));

但总的来说,出于这个原因,最好避免使用strncpy

strncpy()函数类似[与strcpy()函数相似],不同之处在于最多复制n个字节的src。警告:如果src的前n个字节中没有空字节,则放置在dest中的字符串将不会以空结尾


由于
strncpy
调用中的size参数是字符串的长度,因此不包括字符串末尾的null字节,因此目标字符串不会从此调用中以null结尾。

strncpy
的长度限制应基于目标大小,而不是源长度:这是t在strcpy上使用它的意义在于,strcpy只使用源代码中的长度

strncpy(test[j], found, strlen(namesArr[i]));
长度参数来自源数组,这不符合使用
strncpy
的目的。此外,如果函数复制字节的完整限制,则
nul
终止符将不存在,因此应删除代码

strncpy(test[j], found, 19);        // limit to target size, leaving room for terminator
test[j][19] = '\0';                 // add terminator (if copy did not complete)
另一个潜在问题是您是否从文件中正确加载了
namesArr[]
,因为您没有显示代码。

编辑:

对先前的答案稍作修改:

1) 由于您使用的是C字符串,请确保(因为strncpy(…)
不为您执行此操作)为null并终止缓冲区。
2) 使用
strncpy
时,length参数应表示目标字符串字节容量-1(空终止符的空间),而不是源字符串长度

...
int len = strlen(found)
memset(test[j], 0, 20);
strncpy(test[j], found, 19);//maximum length (19) matches array size 
                            //of target string -1 ( test[j] ).
if(len > 19) len = 19; //in case length of found is longer than the target string.
test[j][len+1] = 0;
...

您需要将null终止符附加到
测试[j]
strncpy之后,
strncpy
的长度限制应该基于目标大小,而不是源代码长度:这就是在仅使用源代码长度的strcpy上使用它的意义。为了便于理解和可读性,我们人类:1)遵循公理:每行只有一条语句,并且(最多)每个语句一个变量声明:2)通过一个空行分隔代码块(for、if、else、while、do…while、switch、case、default)。发布的代码似乎缺少以下的#define语句:
MAX\u PL\u LENGTH
strncpy(test[j],found,strlen(namesArr[i]);
-->
strncpy(test[j],found,19);test[j]='\0';
不清楚,
strncpy(test[j],found,strlen(namesArr[i]);
test[j]
中确保一个空字符。这是目的吗?不明白
strlen(namesArr[i])<20
@chux:是的,必须有strlen strlen
strlen()
将始终给予同意。注意:
strncpy(test[j],found,sizeof test[j]-1);
将更易于维护。当一个神奇的数字(如20)出现时看起来,最好只出现一次,让其余的代码使用派生/计算值。@chux我通常会在不是运行时值的地方使用say
#define strize 20
。我硬编码了20,因为该程序是为完成特定任务而设计的,它永远不需要超过19个字符。谢谢你的回答,我明白了当你在说我使用的错误的方法<代码> STRNCYPY()/代码>。你建议我做什么来达到同样的目的?<代码> NeSARARR(0)<代码> > < <代码> >是“Madame Fabantou似乎对我来说更好”,M. Leblanc接着说,Studio \n,<代码> STRSTRESH(<代码> >找到了“勒布朗”这个词的开头。“在
中,现在我只想将“Leblanc”复制到
测试[I]
,而不是“Leblanc,casting”(即仅7个字符),这难道不妨碍使用
strncpy
而不是
strcpy
的优势吗?”?目标尺寸不会出现在任何地方。@WeatherVane-编辑以解决(至少我认为是)您提出的问题。非常感谢。
...
int len = strlen(found)
memset(test[j], 0, 20);
strncpy(test[j], found, 19);//maximum length (19) matches array size 
                            //of target string -1 ( test[j] ).
if(len > 19) len = 19; //in case length of found is longer than the target string.
test[j][len+1] = 0;
...