我在C中有一个赋值编码试图使用C而不是使用shell从文件中删除前导空格。我目前有一个程序可以删除程序中的所有空格。我只是无法想象如何使它只删除实际文本之前的行开头的空格。在c中编码很新,所以我很抱歉,如果这看起来像一个简单的问题。此外,我有我的文件硬编码,但我希望能够传入任何文本文件。为了澄清,我只是尝试删除前导空格并尝试从通过命令行传递的测试文件中执行此操作。我没有使用字符串。
#include<stdlib.h>
#include<string.h>
#include<stdio.h>
void main() {
FILE *fp;
char p;
fp = fopen("mountainList.txt", "r");
while((p=getc(input))!=EOF) {
if(p != 32)
printf("%c",p);
}
fclose(input);
}
Example text file:
this is a test file
this is a file of text
text is in this file
Example output:
this is a test file
this is a file of text
text is in this file
你快到了。只需在循环中需要更多代码。这是我可能会这样做的(你的编码风格可能会有所不同 - 比如尤达条件):
#include<stdlib.h>
#include<string.h>
#include<stdio.h>
int main() {
FILE *fp;
int p;
int at_start = 1;
fp = fopen("mountainList.txt", "r");
while (EOF != (p = getc(input))) {
if (at_start && ' ' == p) continue;
putc(p);
at_start = ('\n' == p);
}
fclose(input);
}
#include <ctype.h>
#include <string.h>
#include <stdio.h>
char *trimLeading(char line[])
{
char *p;
for (p = line; *p && isspace(*p); ++p) ;
return p;
}
void printTrimmedLns(FILE *fp)
{
char line[MAXLINE];
while (fgets(line, MAXLINE, fp))
printf("%s", trimLeading(line));
}
这样打电话:
printTrimmedLns(stdin); /* or whatever input stream you need */
关于编码的几个注释。不要使用硬编码的文件名或数字(称为“魔术数字”),例如
fp = fopen("mountainList.txt", "r");
...
if(p != 32)
它们使您的代码难以阅读,更重要的是,随着程序长度的增长难以维护。相反,将您的文件名作为参数传递给您的程序或从您的代码中读取文件名。而不是使用魔法数字32
,使用字符文字' '
所以很明显,空间是有意的。
如果您需要数字常量或字符串常量,请在代码的开头加上#define
。如果以后需要更改,那么它提供了一个方便的位置来进行单个更改。
虽然使用getc
(fgetc
)没有任何问题,但考虑使用面向行的输入函数一次读取一行输入,例如fgets()
或POSIX getline()
。然后,您可以使用可以自动报告必须删除的空白字符数的字符串函数。
检查每个字符并保持索引或推进指针的替代方法,您可以单独调用strspn
,提供包含您的行的缓冲区,然后是定义要考虑的空白字符的字符串,它将返回初始字符数你的线完全由空白组成。
例如,以下文件将文件名作为程序的第一个参数读取(如果没有给出文件名,则默认从stdin
读取),然后在验证文件打开以供读取后,读取一次一行的行,将该行与包含空格字符strspn
(空格,制表符)的字符串一起传递给" \t"
。 strspn
的返回是完全由空白字符串中的字符组成的初始字符数 - 然后您可以将其用作打印行的偏移量(或索引),省略前导空格,例如
#include <stdio.h>
#include <string.h>
#define MAXC 1024 /* if you need a constant, #define one (or more) */
#define WS " \t" /* leading whitespace characters to remove */
int main (int argc, char **argv) {
char line[MAXC]; /* buffer to hold line (don't skimp on buffer size) */
/* use filename provided as 1st argument (stdin by default) */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
perror ("file open failed");
return 1;
}
while (fgets (line, MAXC, fp)) /* read each line */
printf ("%s", &line[strspn (line, WS)]); /* output w/o leading ws */
if (fp != stdin) fclose (fp); /* close file if not stdin */
return 0;
}
或者,如果您更喜欢使用指针和偏移进行打印,则可以使用以下命令替换对printf
的调用:
printf ("%s", line + strspn (line, WS)); /* output w/o leading ws */
(注意:如果要删除包含所有空格的行,请检查strspn
返回的偏移处的行结尾,并简单地跳过该行)
使用您的示例输入将导致以下结果:
$ /bin/removews <dat/wslines.txt
this is a test file
this is a file of text
text is in this file
正如开头所提到的,采用面向字符的方法来使用getc
读取文件没有任何问题,但是知道将整行读入缓冲区的面向行的方法的另一种选择可以使string.h
中的函数可用用于缓冲区本身。
仔细看看,如果您有其他问题,请告诉我。