C 从FGET中删除换行符

C 从FGET中删除换行符,c,newline,fgets,C,Newline,Fgets,如果这个问题很明显,或者我犯了一个简单的逻辑错误,我很抱歉。我一直在寻找各种方法来摆脱使用fgets产生的换行符,但我在构建时仍然遇到问题。我认为我没有正确地理解某些东西,也没有正确地应用我的“解决方案”。我想说清楚,这是学校的作业。除了我的输出之外,一切都运行得很好,它有不必要的新行 此函数的唯一用途是将名称读入结构数组 void initialize(FILE * ifp, Candidate * electionCandidates, int count) { for (int i =

如果这个问题很明显,或者我犯了一个简单的逻辑错误,我很抱歉。我一直在寻找各种方法来摆脱使用fgets产生的换行符,但我在构建时仍然遇到问题。我认为我没有正确地理解某些东西,也没有正确地应用我的“解决方案”。我想说清楚,这是学校的作业。除了我的输出之外,一切都运行得很好,它有不必要的新行

此函数的唯一用途是将名称读入结构数组

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;