从strncpy()函数中获取奇怪字符
我应该从一个文件中加载一个名称列表,然后在第二个文件中找到这些名称,并将它们加载到一个包含其他数据的结构中(为了简单起见,我将把它们加载到另一个名为“test”的数组中) 第一部分很好,我正在打开一个文件并将所有名称加载到名为namesArr的二维数组中。 第二部分是出现意外字符的地方,我不明白为什么。下面是函数的代码:从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
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 strlenstrlen()
将始终给予同意。注意: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;
...