- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
所以我正在写它应该做到这一点例如
This info is supposed to
be flipped back
for this code.
empty line was above this one.
会变成
to supposed is info This
back flipped be
code. this for
one. this above was line empty
现在我有一个函数可以完美地做到这一点,但我的教授告诉我要逐个字符地读取,然后在遇到新行时处理一行。然后继续到下一行,直到 EOF。
另一方面,我有一个 fgets,我加载整个输入/文件。然后我在我的函数中处理这个问题。另一方面,如果一行长度超过 80 个字符,那么我不应该处理它。
这是我的工作代码,但如何转换它以便它使用 getc() 而不是 fgets?谢谢
void reverser(FILE *input){
char c[82]; //Character size limited per line
if(outputFlag)
fp = freopen(fileName, "a+", stdout);
while (fgets(c, sizeof c, input)!=NULL){
int counter =0;
int x = 0;
while(*(c+x)=='\t' || *(c+x)==SPACE)
x++;
if(*(c+x) == '\n')
continue;
char *pCar[80];
int i, n = 0;
char *tok = strtok(c, " \t\n");
while (tok != NULL && n < 80){
*(pCar+n++) = tok;
tok = strtok(NULL, " \t\n");
}
for(i = n-1; i>=0; --i){ //Counting the char length of the lines
counter+=(int)strlen(*(pCar+i));
if(i)
counter++;
}
if(counter>80){ //Throw error if character length is > 80
fprintf(stderr, "LINE TOO LONG\n");
returnVal = 1;
continue;
}
for(i = n-1; i>=0; --i){
printf("%s", *(pCar+i));
if(i)
putchar(' ');
}
printf("\n");
}
fclose(input);
}
我很想得到一些提示。
最佳答案
这段代码似乎或多或少对我有用。
z.c
#include <stdio.h>
#include <string.h>
char *read_line(char *buffer, size_t buflen, FILE *fp);
void reverser(FILE *input);
char *read_line(char *buffer, size_t buflen, FILE *fp)
{
int c;
char *data = buffer;
char *end = buffer + buflen - 1;
while (data < end && (c = getc(fp)) != '\n')
{
if (c == EOF)
{
*data = '\0';
return (data == buffer) ? NULL : buffer;
}
*data++ = c;
}
if (data < end)
{
*data++ = c;
*data = '\0';
}
else
{
// Overlong line - report error, read and discard to EOL
// or EOF, and return empty string (not even newline).
fprintf(stderr, "Line too long: discarded!\n");
while ((c = getc(fp)) != EOF && c != '\n')
;
*buffer = '\0';
}
return buffer;
}
void reverser(FILE *input)
{
char c[82];
while (read_line(c, sizeof c, input) != NULL)
{
int x = 0;
while (c[x] == '\t' || c[x] == ' ')
x++;
if (c[x] == '\n' || c[x] == '\0')
continue;
char *pCar[80];
int i, n = 0;
char *tok = strtok(c, " \t\n");
while (tok != NULL && n < 80)
{
*(pCar + n++) = tok;
tok = strtok(NULL, " \t\n");
}
for (i = n - 1; i >= 0; --i)
{
printf("%s", *(pCar + i));
if (i)
putchar(' ');
}
printf("\n");
}
// fclose(input); // Don't close what you didn't open!
}
int main(void)
{
reverser(stdin);
return 0;
}
我对 reverser()
进行了最小的更改,删除了不再相关的代码,使用 c[x]
代替 *(c + x)
因为它更容易键入和阅读,用 ' '
替换 SPACE
,删除代码以重新打开标准输出等。
该程序使用以下方式干净地编译:
gcc -Wall -Wextra -Werror z.c -o z
(在带有 GCC 5.1.0 的 Ubuntu 14.04 衍生版本上进行测试。)
示例输出:$ ./z
pedagogical anti-orthodoxy grammatically correct infelicitous nonsense munged with catatonic isotopes of prejudice and grunge lead to positive recognition of abusive memes in the genetic diversity of alphabets.
Line too long: discarded!
pedagogical anti-orthodoxy grammatically correct infelicitous nonsense
nonsense infelicitous correct grammatically anti-orthodoxy pedagogical
munged with catatonic isotopes of prejudice and grunge lead
lead grunge and prejudice of isotopes catatonic with munged
to positive recognition of abusive memes in the genetic diversity of alphabets.
alphabets. of diversity genetic the in memes abusive of recognition positive to
$
最初,有很多与该问题相关的评论,寻求并获得问题的说明并概述解决方案。这些评论已全部删除 - 请参阅此 MSO question 。幸运的是,我开发答案的浏览器一夜之间保留了对该问题的评论。我并不是说这些评论很棒;我并不认为这个问题很棒;我并不声称我的答案很好。我同意 JQ143 的许多评论应该是对问题的编辑。我确实断言这些评论为我的回答提供了必要的背景,不应该被批量删除。
下面的评论并非逐字复制;它们是经过精心策划的。 wildplasser 的几条评论已被省略。
乔纳森·莱夫勒评论道:
There are similar questions on SO already. Why would you want to use
getc()
instead offgets()
? You need to process whole lines, so reading whole lines makes a lot of sense. One easy way around it is to write your own function, maybechar *read_line(char *buffer, size_t buflen, FILE *fp)
that usesgetc()
but simulatesfgets()
. More likely, he has in mind that you'll usegetc()
to read characters into the first word, then the second, then ..., and when you hit EOL (newline), you print out the saved words in reverse order, zero things, and repeat.
我注意到BLUEPIXY的answer实质上实现了“使用 getc()
一次读取一个单词”版本的代码。
ChuckCottrill注意到:
The instructor wants you do demonstrate that you know how to build your own
fgets()
function using thegetc()
function as a base, or perhaps gather one word at a time, pushing those words onto a stack, and then pop them from the stack and emit them.
JQ143评论(但理想情况下应该修改问题以说明):
So what he basically wants is to keep adding characters to an array until you hit newline. Once you hit newline you can process that array and print them backwards. Then repeat this with character starting after that old newline... Any idea how I can just use
getc()
? He said it should be easy to fix.@ChuckCottrill my professor is saying the
fgets
won't work with this program. He said it'll break, which I don't see how it could.
我注意到:
That's what my proposed
read_line()
does and the existingfgets()
does. Ignoring buffer overflow checking, that's trivial:char *read_line(char *buffer, size_t buflen, FILE *fp)
{
int c;
char *data = buffer;
while ((c = getc(fp)) != '\n')
{
if (c == EOF)
{
*data = '\0';
return (data == buffer) ? 0 : buffer;
}
*data++ = c;
}
*data++ = c;
*data = '\0';
return buffer;
}Adding buffer overflow checking is not difficult, but is left as an exercise for you. If you need to ignore lines that are too long, or read and discard the excess material if the line is too long, that is also easily done.
(该代码在我的正常编译器选项下无法编译,因为未使用 buflen
。)
JQ143回复:
I am sorry but I am having a hard time figuring out how to incorporate that into my program.
我的回复是:
Change:
while (fgets(c, sizeof c, input)!=NULL){
towhile (read_line(c, sizeof c, input)!=NULL){
Note that using the name
c
for an array ofchar
is not conventional;c
normally denotes a singlechar
variable:char c;
.Also note that the code
if(outputFlag) fp = freopen(fileName, "a+", stdout);
makes this function logically incohesive. The calling code should handle the redirection. It can either pass the output file stream to this function (sovoid reverser(FILE *input, FILE *output)
) or arrange it so thatstdout
is modified withfreopen()
. But this function should not be accessing the global variablesfileName
andoutputFlag
.
jxh注意到:
See: fgets implementation (K&R); it was the top link of my Google search.
As to how the program might fail, if a line length
N
is longer than 80 characters, it looks like you will reverse the last (N % 81
) bytes of the line (81 sincesizeof(c)
is 82).
JQ143回复:
@jxh so if a line length is greater than 80. It will just throw an stderr saying line too long. Which is actually part of the program.
jxh 回应:
You print an error, but you continue the loop.
JQ143:
@jxh Oh..according to my professor, I have to process lines that are less than 80 but throw an error for those that are longer.
jxh:
You process the remaining lines, yes. But, you also process the rest of the currently too long line. If the line was 100 bytes long, you read in 81 bytes of it. When you determine the line is too long, you print your error, and continue. When you continue, you end up reading in 19 more bytes of the too long line. 100 % 81 is 19.
JQ143:
@jxh you are actually right. I'll try to fix that.
JQ143:
Thank you!, but upon doing so [changing
fgets()
toread_line()
] my program went into a crazy infinite loop.
我反驳道:
I just compiled the code extracted from my comment (the
read_line()
function), and it seems to work OK as long as you don't have overlong lines. A revised version of the code is:char *read_line(char *buffer, size_t buflen, FILE *fp)
{
int c;
char *data = buffer;
char *end = buffer + buflen - 1;
while (data < end && (c = getc(fp)) != '\n')
{
if (c == EOF)
{
*data = '\0';
return (data == buffer) ? 0 : buffer;
}
*data++ = c;
}
if (data < end)
*data++ = c;
else
ungetc(c, fp);
*data = '\0';
return buffer;
}
该函数的这种变体会在一行中留下额外的数据,以便下次调用该函数时读取,就像 fgets()
所做的那样。
JQ143:
Any hints on how to deal with lines longer than 80 chars?
Using your variable name, I'd use
char c[4096];
while (read_line(c, sizeof(c), input) != 0)
{
if (strlen(c) > 80)
{
fprintf(stderr, "Too long at %zu (line <<%s>>)\n", strlen(c), c);
continue; /* or break; */
}
...reading lines up to 4 KiB and only processing ones that are short enough. That runs the (rather small) risk that you'll get a line of 4150 bytes, and reject the first 4095 bytes, but process the remainder as a 55 byte line. If that's not acceptable, modify the code in
read_line()
to detect overlong input (passing an 82 byte buffer), and have it gobble to EOL or EOF when necessary.
这基本上肯定了 @jxh 关于行太长时代码行为的说法,并概述了解决该问题的方法。
JQ143:
@JonathanLeffler So I pretty much want to throw an stderr (just once) if I detect a sentence is longer than 80 chars. I think reading it up to 80 and not reading the rest is a good way. But how can I do that in
read_line()
instead of doing that weird counter stuff in my other method? I also wanna thank you for helping me. I appreciate it so much.
此时,已经可以给出答案了;规范足够清晰——尽管信息应该在问题中而不是评论中。
查克科特里尔指出:
An interesting variant solution would be to build a
readline
function that would increase the allocated space (seerealloc
) as the buffer size was exhausted...
这就是 POSIX getline()
.
如chux noted ,我的代码不处理零的 buflen
。在我看来,sizeof(object)
在 C 中永远不会产生 0
,所以你必须尝试遇到这个问题。对该函数的一项粗略修改是:
assert(*buffer != 0 && buflen != 0 && fp != 0);
if (buffer == 0 || buflen == 0 || fp == 0)
return 0;
assert
强制在开发环境中正确使用;该测试模拟生产环境中的 EOF,避免运行时出现灾难性的错误行为。
关于c - 如何在我的程序中使用 getc() 而不是 fgets(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29931567/
我有一个包含数字和整数的文件,我只想读取整数, 如果它们令人讨厌,请忽略宏,但是我只需要有整数,但是我必须确保还要读取字符串,然后忽略它们 我必须在这里修改什么: #include #include
我有一个这样格式化的txt文件: MyDepartureTown MyDestinationTown 123.45 Vehicle 12 我正在尝试将数据导入到我的 C 程序中。这是我用来实现这一目标
我创建了一个简单的文件,使用 flex,它生成了一个文件 lex.yy.c,现在,我想把它放到 C++ 程序中。 %{ #include %} %% stop printf("Stop co
我的一个程序用 c++ 代码生成一个大文件。有没有办法从另一个C++类调用将生成的代码插入其中? 这是一个小例子,可以清楚地说明我想要实现的目标。 生成的文件示例: FirstClass first
我需要了解我的程序“检查输入十六进制消息的第三个位置” 程序将采用十六进制值输入消息。例如0x0123456789abcdef 程序将检查输入消息的第三个位置,即 0 现在程序将采用另一条十六进制值的
当我将输入从输入文件重定向到 yacc 程序时,在它完成解析文件后,我希望 yacc 解析器打印其所做操作的摘要。如果我通过键盘输入内容然后按 Ctrl+D,我希望它执行相同的操作。有办法做到这一点吗
我正在扫描该文件,但它有两种不同的结构。 文件: ParisRoubaix "Marco MARCATO" 33 UAD ITA 26 5:43:31 ParisRoubaix "Sam BEWLEY
我想将winsock2.lib 添加到我的程序中,但不希望将其包含到最终的可执行文件中。有什么方法可以让我动态加载与winsock2关联的dll吗?如果没有,是否有任何 dll(Windows 附带)
我尝试了一个基本程序来将数据从数据库表检索到java程序中。编译结束后,运行代码时出现异常。控制台中没有显示错误。显示异常消息 import java.sql.*; public class clas
我想用 C++ 创建一个跨平台安装程序。它可以是任何压缩类型,例如 zip 或 gzip,像普通安装程序一样嵌入程序本身。我不想在不同的平台、linux 和 windows 上创建很多更改。如何跨平台
每次尝试用鼠标输入两个顶点时,我都会崩溃。我最近改变了组织每个形状的方式,以确保新形状与旧形状重叠。 这个项目的想法是制作各种交互式 Canvas 。用户可以在直线、三角形和矩形之间进行选择,然后选择
我想在我的程序中显示以下文本。当我在 python 中粘贴以下文本时,它会将反斜杠解释为转义序列并弄乱我的 ascii 艺术..任何解决这个问题的想法极客。这是我的文本想出现在我的节目中 _ _
我正在尝试加载名为 Tut16_ReadText.txt 的文件,并使其运行程序以输出其重或轻。 我收到了粘贴在下面的错误。我无法抽出时间让这个程序运行。谁能解释一下我必须做什么才能使这个程序正常工作
我想使用命令行将列表作为参数传递,例如: $python example.py [1,2,3] [4,5,6] 我希望第一个列表 [1,2,3] 成为 first_list,[4,5,6] 成为 se
在分析 C# 应用程序时,我发现名为“ThePreStub”的系统 (?) 方法中有相当多的 CPU 使用率。这是什么? 最佳答案 参见:CLR Inside out - The Performanc
关闭。这个问题需要更多focused .它目前不接受答案。 想改进这个问题吗? 更新问题,使其只关注一个问题 editing this post . 关闭 9 年前。 Improve this qu
我正在用 Python 开发一个游戏,想知道如何给它自己的图标。我使用的是 Windows 计算机,没有安装 Python 的额外东西。哦,我也在使用 3.3 版,这甚至可能吗? P.S 我在 Sta
我正在使用 tkinter 使用 Python 开发一个项目,该项目将允许对 IP 地址进行地理定位。我有原始转换,我可以获取 IP 地址并知道城市、州、国家、经度、纬度等。我想知道是否有任何方法可以
我编写了一个程序,您可以在其中选择任意数字并将其与任意数字的幂相关联。代码运行正常,直到它到达某个部分,然后我必须输入一个字符以使其移动到代码的下一部分。这就是我的意思: #include int
我正在编写“HACKING Art Of Exploitation”一书练习 Convert2.c 第 61 页。 这是我的代码。下面是我的问题。 #include void usage(char
我是一名优秀的程序员,十分优秀!