C 从FGET中删除换行符
如果这个问题很明显,或者我犯了一个简单的逻辑错误,我很抱歉。我一直在寻找各种方法来摆脱使用fgets产生的换行符,但我在构建时仍然遇到问题。我认为我没有正确地理解某些东西,也没有正确地应用我的“解决方案”。我想说清楚,这是学校的作业。除了我的输出之外,一切都运行得很好,它有不必要的新行 此函数的唯一用途是将名称读入结构数组C 从FGET中删除换行符,c,newline,fgets,C,Newline,Fgets,如果这个问题很明显,或者我犯了一个简单的逻辑错误,我很抱歉。我一直在寻找各种方法来摆脱使用fgets产生的换行符,但我在构建时仍然遇到问题。我认为我没有正确地理解某些东西,也没有正确地应用我的“解决方案”。我想说清楚,这是学校的作业。除了我的输出之外,一切都运行得很好,它有不必要的新行 此函数的唯一用途是将名称读入结构数组 void initialize(FILE * ifp, Candidate * electionCandidates, int count) { for (int i =
void initialize(FILE * ifp, Candidate * electionCandidates, int count)
{
for (int i = 0; i < count; i++)
{
fgets (electionCandidates[i].name , 20 , ifp);
if (electionCandidates[i].name[strlen(electionCandidates[i].name) - 1] == '\n')
{
electionCandidates[i].name[strlen(electionCandidates[i].name) - 1] = '\0';
}
}
}
void初始化(文件*ifp,候选者*election候选者,整数计数)
{
for(int i=0;i
当我尝试运行时,会显示以下内容:“隐式声明库函数“strlen”,类型为unsigned long(constant char*)”1)不,不一定是“显而易见的”-问得好
2) 是的,您想使用“strlen()”
3) 听起来你好像忘记了定义“strlen()”的#include
#包括
#包括
...
char*trim(char*s){
int i=strlen(s)-1;
如果((i>0)和&(s[i]='\n'))
s[i]='\0';
返回s;
}
这是我的看法
#include <stdio.h>
#include <string.h> // to fix the warning
...
// remove NL left by fgets, with protection
void trimnl (char *s) {
char *pnl = s + strlen(s);
if (*s && *--pnl == '\n')
*pnl = 0;
}
void initialize(FILE* ifp, Candidate* electionCandidates, int count) {
for (int i = 0; i < count; i++) {
fgets (electionCandidates[i].name, 20, ifp);
trimnl(electionCandidates[i].name);
}
}
这是批评的基础上,有符号算术与无符号值。但是,批评不适用,因为在这种情况下,最终结果(如果strlen=0)等同于:
char *pnl = s - 1;
不存在无符号算术问题,但存在未定义的行为问题。这就是我更改代码的原因。以后,使用
-Wall
编译以启用编译警告
根据您的编译器,您将获得关于如何解决此问题和类似问题的有用建议(在本线程的其他部分的一个答案中已经讨论过-例如,使用Clang编译将警告您缺少
include
。是您的家庭作业吗?家庭作业不是问题。所以在这里帮助你学习。你一直在做自己的事,自己尝试解决问题,发布相关代码和任何错误消息,这里的人总是乐于提供帮助。然而,那些不先尝试自己的工作,只想让别人做作业的人——通常在这里或在他们以后的职业生涯中都没有那么成功地获得帮助。你的代码很好,只是没有包含。我不知道为什么其他一些答案会引入一个复杂的解决方案。strlen(string)-正整数
大多数情况下都会导致灾难,而且绝大多数情况下是不必要的。删除换行符的技巧(可爱或糟糕,取决于你怎么看)是strok(election候选者[I].name,“\n”)代码>哈,是的,我确实忘记了。感谢您的快速回复,它提供了很好的洞察力。我将尝试修复我的代码。非常感谢。当使用空终止字符
覆盖换行符
时,您可以使用空字符'\0'
的字符表示形式,如上所示,也可以使用其整数值0
。两者是等价的。(即,s[i]=0;
)因此,如果看到其中一种形式,就知道这两种形式是等效的。如果(i>=0
不能防止strlen=0的强制转换。strlen
函数返回一个size\t
,这是一种无符号类型,因此分配(size\t)0-1
到int
会导致实现定义的行为。相反,在继续之前,请检查*s!=0
或保存strlen(s)
,而不使用-1
。strlen(字符串)-正整数
大多数情况下都会导致灾难,而且绝大多数情况下是不必要的。要获得更大的保存空间,甚至更灵活的方式来切断尾随可能的行尾序列(因为它不一定总是只有一个字符),您可能想看看这个答案:如果(*s),那么做有点晚了
一旦您已指向超出string@MattMcNabb:该指针不会造成任何伤害,但我承认它是未定义的行为。请参见编辑。@alk:您的注释不适用于此处,但我已更改代码。“…不适用于此处,但我已更改…”应改为“…不再适用于此处,因为我已更改…”不应该吗?;-)但是无论如何,清理…@alk:对不起,我的意思是,由于表达式求值的顺序,你对strlen()-int的评论不适用于我编写的特定代码,但是没有必要争论它,因为我更改了代码以避免UB。请参阅编辑。好的,以后不要在启用警告的情况下编译。堆栈溢出已发出声音!:)
char *pnl = s + strlen(s) - 1;
char *pnl = s - 1;