使用C更改文件中单词的第一个字母的大小写

时间:2018-02-21 12:03:15

标签: c file-handling

我正在尝试使用C来改变文件中第一个字母的大小写。

例如,如果文件包含句子:good morning.how are you? 然后它将更改为Good Morning.How Are You?

我尝试了很多,但无法产生预期的效果。 谁能帮我?我使用这段代码:

#include <stdio.h>

void main() {
    FILE *fp1;
    char ch;
    int p;

    fp1 = fopen("asiftext.txt", "a+");
    ch = fgetc(fp1);
    if (ch >= 'a' && ch <= 'z') {
        fseek(fp1, -1, 1);
        ch = toupper(ch);
        fputc(ch, fp1);
    }
    while ((ch = fgetc(fp1)) != EOF) {
        if (ch == ' ' || ch == '\n') {
            ch = fgetc(fp1);
            if (ch == EOF)
                break;
            if (ch >= 97 && ch <= 122) {
                fseek(fp1, -1, 1);
                fputc(ch - 32, fp1);
            }
        }
    }
    /*ch = fgetc(fp1);
    p = ftell(fp1);
    printf("p1=%d", p);
    printf("%c\n", ch);
    fseek(fp1, -1, 1);
    fputc(ch - 32,fp1);
    ch = fgetc(fp1);
    printf("c=%c\n", ch); */
    fclose(fp1);
}

3 个答案:

答案 0 :(得分:0)

修改文件是个坏主意。为此使用标准流是麻烦且低效的。

这是一个简单的过滤器,可以读取stdin并将修改过的单词写入stdout

#include <ctype.h>
#include <stdio.h>

int main(void) {
    int c, lastc = '\n';

    while ((c = getchar()) != EOF) {
        if (!isalpha(lastc))
            c = toupper(c);
        putchar(c);
        lastc = c;
    }
    return 0;
}

请注意,上述代码适用于ASCII文本文件。它可能不适用于非ASCII文件,特别是如果它们使用UTF-8等多字节编码进行编码。

答案 1 :(得分:0)

转换为标题案例时出现的一个问题是,“在一个单词中触发第一个字符大写的可接受的前面字符是什么?”有时,如您的示例中所示,您可能希望将Morning.Howhow视为单独的单词并大写。其他时候,您可能只想考虑空格后的单词。

您可以通过指定一个结尾字符列表(下面为ends)来定制,然后将第一个字符转换为大写字母。您可以设置定义字符串常量的宏,将第二个短字符串传递给您的标题函数,或者只在函数本身中指定ends列表。

通常,我不会在由点分隔符组成的字符串中大写,但它没有任何问题。这就是ends列表的灵活性带来红利的地方。您只需定制字符串以满足您的需求。一个例子是:

/** convert string to title case based on 'ends'.
 *  returns pointer to 'str' with words converted to 
 *  initial uppercase if the word follows one of the 
 *  characters specified in 'ends'.
 */
char *str2title (char *str)
{
    if (!str) return NULL;    /* handle NULL and empty-string */
    if (!*str) return str;

    char *p = str,            /* pointer to string */
        *ends = " \t\n.",     /* set of acceptable ends */
        last = ' ';           /* previous character seen */

    for (; *p; p++) {                     /* loop over string */
        for (char *e = ends; *e; e++)     /* loop over ends */
            /* if last is end and current is lowercase */
            if (last == *e && ('a' <= *p && *p <= 'z'))
                *p += 'A' - 'a';          /* convert to upper */
        last = *p;
    }

    return str;
}

有很多方法可以解决这个问题。向他们学习。

答案 2 :(得分:-1)

以下提议的代码:

  1. 干净地编译
  2. 使用OPs算法,疣和所有
  3. 正确检查并处理任何错误
  4. 使用适当的水平间距:在逗号后面,在逗号之后,在分号之后,围绕C运算符以便于阅读和理解
  5. 记录每个头文件包含的原因
  6. 评论代码中关键点的状态
  7. 将评论纳入OP问题
  8. 使用头文件ctype.h中的设施来避免加密数字等
  9. 一致地缩进代码,每个缩进级别使用4个空格
  10. 现在,建议的代码:

    #include <stdio.h>    // fopen(), perror(), fgetc(), fclose(),
                          // fseek(), fputc(),
                          // FILE, EOF
    #include <stdlib.h>   // exit(), EXIT_FAILURE
    #include <ctype.h>    // toupper(), isspace(), isalpha()
    
    
    int main( void )
    {
        int ch;
    
        FILE *fp1 = fopen( "asiftext.txt", "r+" );
        if( !fp1 )
        {
            perror( "fopen failed" );
            exit( EXIT_FAILURE );
        }
    
        // implied else, fopen successful
    
        while( ( ch = fgetc( fp1 ) ) != EOF )
        {
            if( !isspace( ch ) )
            {
                continue;
            }
    
            // when here, 'ch' is a 'white space' char
            if( ( ch = fgetc( fp1 ) ) == EOF )
            {
                break;
            }
    
            // when here, 'ch' is possibly the
            // first letter of a word
            if( isalpha( ch ) )
            {  // then 'ch' is alphabetic
                // adjust file pointer
                if( fseek( fp1, -1, SEEK_CUR ) )
                {
                    perror( "fseek failed" );
                    fclose( fp1 );
                    exit( EXIT_FAILURE );
                }
    
                // implied else, fseek successful
    
                // overwrite with uppercase char
                fputc( toupper( ch ), fp1 );
            }
        }
    
        fclose(fp1);
    }
    

    以下提出的代码实现了一个(两个状态)状态机,并解决了OPs算法的缺点。

    #include <stdio.h>    // fopen(), perror(), fgetc(), fclose(),
                          // fseek(), fputc(),
                          // FILE, EOF
    #include <stdlib.h>   // exit(), EXIT_FAILURE
    #include <ctype.h>    // toupper(), isspace(), isalpha()
    
    enum state { notInWord, InWord };
    
    int main( void )
    {
        enum state currentState = notInWord;
    
        int ch;
    
        FILE *fp1 = fopen( "asiftext.txt", "r+" );
        if( !fp1 )
        {
            perror( "fopen failed" );
            exit( EXIT_FAILURE );
        }
    
        // implied else, fopen successful
    
    
        while(  (ch = fgetc( fp1 ) ) != EOF )
        {
            if( notInWord == currentState )
            {
                if( isalpha( ch ) )
                {
                    currentState = InWord;
    
                    // adjust file pointer
                    if( fseek( fp1, -1, SEEK_CUR ) )
                    {
                        perror( "fseek failed" );
                        fclose( fp1 );
                        exit( EXIT_FAILURE );
                    }
    
                    // implied else, fseek successful
    
                    // overwrite with uppercase char
                    fputc( toupper( ch ), fp1 );
                }
    
                else // not alpha
                {
                    currentState = notInWord;
                }
            }
    
            else  // currentState = InWord
            {
                if( !isalpha( ch ) )
                {
                    currentState = notInWord;
                }
            }
        }
    
        fclose(fp1);
    }
    

    这是在更正的源代码副本运行时更正的代码的输出:

    #Include <Stdio.H>    // Fopen(), Perror(), Fgetc(), Fclose(),
                          // Fseek(), Fputc(),
                          // FILE, EOF
    #Include <Stdlib.H>   // Exit(), EXIT_FAILURE
    #Include <Ctype.H>    // Toupper(), Isspace(), Isalpha()
    
    Enum State { NotInWord, InWord };
    
    Int Main( Void )
    {
        Enum State CurrentState = NotInWord;
    
        Int Ch;
    
        FILE *Fp1 = Fopen( "Asiftext.Txt", "R+" );
        If( !Fp1 )
        {
            Perror( "Fopen Failed" );
            Exit( EXIT_FAILURE );
        }
    
        // Implied Else, Fopen Successful
    
    
        While(  (Ch = Fgetc( Fp1 ) ) != EOF )
        {
            If( NotInWord == CurrentState )
            {
                If( Isalpha( Ch ) )
                {
                    CurrentState = InWord;
    
                    // Adjust File Pointer
                    If( Fseek( Fp1, -1, SEEK_CUR ) )
                    {
                        Perror( "Fseek Failed" );
                        Fclose( Fp1 );
                        Exit( EXIT_FAILURE );
                    }
    
                    // Implied Else, Fseek Successful
    
                    // Overwrite With Uppercase Char
                    Fputc( Toupper( Ch ), Fp1 );
                }
    
                Else // Not Alpha
                {
                    CurrentState = NotInWord;
                }
            }
    
            Else  // CurrentState = InWord
            {
                If( !Isalpha( Ch ) )
                {
                    CurrentState = NotInWord;
                }
            }
        }
    
        Fclose(Fp1);
    }