在从某个文件(或标准输入)给定一行时,如何减少额外空格并将标签转换为单个空格?

时间:2017-06-07 18:08:31

标签: c fgets spaces

给定一个存在于数组中的行。就像在这种情况下:

dst

如何将所有额外空间减少到单个空间,并将所有选项卡(任意两个单词之间)减少到单个空格。

例如:
在这一行:

char line[50];
while (fgets(line,50, input_file) != NULL) {
 // how can i do it here..
}

需要:

   a b   abb     ace    ab 

2 个答案:

答案 0 :(得分:1)

像这样:

#include <stdio.h>

char *reduce_and_trim(char *s);

int main(void) {
    FILE *input_file = stdin;
    char line[50];
    while (fgets(line,50, input_file) != NULL) {
        printf("'%s'\n", reduce_and_trim(line));
    }
    fclose(input_file);
}

#include <string.h>

char *reduce_and_trim(char *s){
    static const char *whitespaces = " \t\n";//\t:tab, \n:newline, omit \f\r\v
    size_t src = strspn(s, whitespaces);//Trim of the beginning
    size_t des = 0;//destination
    size_t spc = 0;//number of whitespaces

    while(s[src] != '\0'){
        if((spc = strspn(s+src, whitespaces)) != 0){
            src += spc;
            s[des++] = ' ';//reduce spaces
        } else {
            s[des++] = s[src++];
        }
    }
    if(des && s[des-1] == ' ')
        s[des-1] = 0;//Trim of end
    else
        s[des] = 0;

    return s;
}

答案 1 :(得分:1)

这是一个简单的解决方案:

char line[50];
while (fgets(line, sizeof line, input_file) != NULL) {
    size_t i, j;
    for (i = j = 0; line[i] != '\0'; i++) {
        if (isspace((unsigned char)line[i])) {
            while (isspace((unsigned char)line[++i]))
                continue;
            if (line[i] == '\0')
                break;
            if (j != 0)
                line[j++] = ' ';
        }
        line[j++] = line[i];
    }
    line[j] = '\0';
    printf("reduced input: |%s|\n", line);
}

既然这是作业,这里有一些额外的问题要回答:

  • 哪些包含文件是必需的?
  • 为什么需要演员(unsigned char)line[i]
  • 如果从input_file读取超过50个字节的行,将会发生什么?
  • 上一个问题出了什么问题?