在c中连接两个单独字符串的大写字母

时间:2015-06-17 12:45:05

标签: c arrays string scanf

我正在为即将到来的考试做练习题,但似乎无法找出问题的目标是:

编写C程序以读取两个字符串s1s2。每个字符串的最大大小为25.形成两个名为upperlower的新字符串。 Lower由s1s2连接的小写字母组成,而upper包含两个字符串的大写字母的连接。

例如: 输入:

  

s1:GREENblue
s2:busCAR

输出:

  

鞋帮:GREENCAR
更低:bluebus

我已经尝试了几天但却未能完全理解它。

这是我到目前为止所拥有的:

#include <stdio.h>
#include <math.h>
#include <string.h>
#include <conio.h>

int main()
{
    int i, j;
    char s1[25];
    char s2[25];
    char upper[25];
    char lower[25];

    printf ("Please enter first string: ");
    scanf ("%s", &s1);
    printf ("Please enter second string: ");
    scanf ("%s", &s2);

    strcat (s1, s2);

    for (i=0; i<strlen(s1); i++)
    {
        if (s1[i]>=65 && s1[i] <= 90)
        {
            upper[i] = s1[i];
        }
        else
        {
            lower[i] = s1[i];
        }
    }
    printf ("Upper: %s\n", upper);
    printf ("Lower: %s\n", lower);
}

4 个答案:

答案 0 :(得分:1)

在您的代码中,使用strcat()

 strcat (s1, s2);

s1可能没有足够的内存来保存连接字符串。在这种情况下,它会调用undefined behaviour

从手册页

  

如果dest不够大,程序行为是不可预测的;缓冲区溢出是攻击安全程序的最佳途径。

根据您的要求

  

The maximum size of each string is 25

您需要一个长度为25 X 2的目标缓冲区(对于char s)+ 1(对于null)。

此外,它表示,您需要s1s2分别拥有26元素,以容纳空值。

根据您的要求,您的计划需要进行某些设计更改,如

  1. 您需要s1s2分别拥有26元素,以容纳空值。

  2. upperlower都必须具有输入大小总和的大小。如果s1s2都是完全大写(或小写),请考虑这种情况。因此,您需要upper[51]lower[51]

答案 1 :(得分:0)

这是我迄今为止所拥有的::)

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

#define N   25

int main(void)
{
    char s1[N];
    char s2[N];
    char *upper, *lower;
    char *p, *q;
    size_t n1, n2;

    printf( "Please enter first string: " );
    fgets( s1, N, stdin );

    printf( "Please enter second string: " );
    fgets( s2, N, stdin );

    n1 = 0; n2 = 0;

    for ( p = s1; *p; ++p )
    {
        if ( isupper( ( unsigned char )*p ) ) ++n1;
        else if ( islower( ( unsigned char )*p ) ) ++n2;
    }

    for ( p = s2; *p; ++p )
    {
        if ( isupper( ( unsigned char )*p ) ) ++n1;
        else if ( islower( ( unsigned char )*p ) ) ++n2;
    }

    upper = NULL; lower = NULL;

    if ( n1 && ( upper = ( char * )malloc( n1 + 1 ) ) )
    {
        q = upper;

        for ( p = s1; *p; ++p )
        {
            if ( isupper( ( unsigned char )*p ) ) *q++ = *p;
        }

        for ( p = s2; *p; ++p )
        {
            if ( isupper( ( unsigned char )*p ) ) *q++ = *p;
        }

        *q = '\0';
    }       

    if ( n2 && ( lower = ( char * )malloc( n1 + 1 ) ) )
    {
        q = lower;

        for ( p = s1; *p; ++p )
        {
            if ( islower( ( unsigned char )*p ) ) *q++ = *p;
        }

        for ( p = s2; *p; ++p )
        {
            if ( islower( ( unsigned char )*p ) ) *q++ = *p;
        }

        *q = '\0';
    }       

    if ( upper ) printf( "Upper: %s\n", upper );
    if ( lower ) printf( "Lower: %s\n", lower );

    free( upper );
    free( lower );

    return 0;
}

程序输出可能看起来像

Please enter first string: GREENblue
Please enter second string: busCAR
Upper: GREENCAR
Lower: bluebus

如果您的编译器支持可变长度数组,那么您可以使用VLA代替动态分配的数组。

这是一个使用VLA的程序

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

#define N   25

int main(void)
{
    char s1[N];
    char s2[N];

    printf( "Please enter first string: " );
    fgets( s1, N, stdin );

    printf( "Please enter second string: " );
    fgets( s2, N, stdin );

    size_t n1 = 0, n2 = 0;

    for ( const char *p = s1; *p; ++p )
    {
        if ( isupper( ( unsigned char )*p ) ) ++n1;
        else if ( islower( ( unsigned char )*p ) ) ++n2;
    }

    for ( const char *p = s2; *p; ++p )
    {
        if ( isupper( ( unsigned char )*p ) ) ++n1;
        else if ( islower( ( unsigned char )*p ) ) ++n2;
    }


    char upper[n1 + 1];
    char lower[n2 + 1];

    if ( n1 )
    {
        char *q = upper;

        for ( const char *p = s1; *p; ++p )
        {
            if ( isupper( ( unsigned char )*p ) ) *q++ = *p;
        }

        for ( const char *p = s2; *p; ++p )
        {
            if ( isupper( ( unsigned char )*p ) ) *q++ = *p;
        }

        *q = '\0';
    }       

    if ( n2 )
    {
        char *q = lower;

        for ( const char *p = s1; *p; ++p )
        {
            if ( islower( ( unsigned char )*p ) ) *q++ = *p;
        }

        for ( const char *p = s2; *p; ++p )
        {
            if ( islower( ( unsigned char )*p ) ) *q++ = *p;
        }

        *q = '\0';
    }       

    if ( n1 ) printf( "Upper: %s\n", upper );
    if ( n2 ) printf( "Lower: %s\n", lower );


    return 0;
}

答案 2 :(得分:0)

您仍有问题:如果输入的字符串长度超过23个字符会怎样?你的程序会崩溃。

如果最大大小为25个字符,则必须将数组的大小设置为26而不是25,以解释终止NULL。

然后你必须设置s1 [N-1] =&#39; \ 0&#39;和s2 [N-1] =&#39; \ n&#39;为了安全。 如果为第一个字符串输入的内容太长,第二个字符串将最终成为剩余字符,忽略在第二个字符串提示后输入的任何内容。

答案 3 :(得分:-1)

我认为你有一般的想法,但错过了一些重要的细节:

  • 不要使用strcat来连接两个字符串。你已经将它们中的每一个都放在自己的缓冲区中,如果你要这样做,你最好确保你有足够的内存来容纳更大的结果字符串。

  • if (s1[i]>=65 && s1[i] <= 90)这个条件很适合检查大写字母,但它的否定会让你得到其他一切,包括小写字母,数字等。所以最好有3个案例(大写,小写,其他一切)只是为了安全起见。

  • 如果要打印上/下数组的内容,请确保附加'\0'字符,以便它们被打印函数解释为字符串。

    j=0; //iterator for lower
    k=0; //iterator for upper
    for (i=0; i<strlen(s1); i++)
    {
        if (s1[i]>='A' && s1[i] <= 'Z') // a bit more clear
        {
            upper[k++] = s1[i];
        }
        else
        {
            if (s1[i]>='a' && s1[i] <= 'z')
            {
                 lower[j++] = s1[i];
            }
            else
            {
                //print something or just exit...
            }
         }
    }
    
    for (i=0; i<strlen(s2); i++)
    {
        if (s2[i]>='A' && s2[i] <= 'Z') // a bit more clear
        {
            upper[k++] = s2[i];
        }
        else
        {
            if (s2[i]>='a' && s2[i] <= 'z')
            {
                lower[j++] = s2[i];
            }
            else
            {
                 //print something or just exit...
            }
        }
    }
    //add the string terminator character
    lower[j] = '\0';
    upper[k] = '\0';
    
    //print the result
    printf ("Upper: %s\n", upper);
    printf ("Lower: %s\n", lower);
    

这应该可以胜任。

相关问题