在c中连接两个单独字符串的大写字母
concatenating uppercase letters of two separate strings in c
我正在为即将到来的考试做练习题,但似乎无法弄清楚 objective 是:
编写一个 C 程序来读取两个字符串 s1
和 s2
。每个字符串的最大长度为 25。形成两个新的字符串,称为 upper
和 lower
。 Lower 由 s1
和 s2
的小写字母串联而成,而 upper
包含两个字符串的大写字母的串联。
例如:
输入:
s1: GREENblue
s2: busCAR
输出:
upper: GREENCAR
lower: 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);
}
在您的代码中,在 strcat()
的用法中
strcat (s1, s2);
s1
可能没有足够的内存来保存连接的字符串。在这种情况下,它会调用 undefined behaviour.
来自手册页,
If dest
is not large enough, program behavior is unpredictable; buffer overruns are a favorite avenue for attacking secure programs.
根据您的要求
The maximum size of each string is 25
您需要一个长度为 25 X 2(对于 char
s)+ 1(对于 null)的目标缓冲区。
此外,它表明,您需要 s1
和 s2
来包含 26
个元素,每个元素都用于容纳 null。
根据您的要求,您的程序需要进行某些设计更改,因为
您需要 s1
和 s2
具有 26
个元素,每个元素都用于容纳 null。
upper
和 lower
的大小都必须是输入大小的总和。想想 s1
和 s2
都完全大写(或小写)的场景。所以,你需要 upper[51]
和 lower[51]
.
这是我目前的情况::)
#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 = '[=10=]';
}
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 = '[=10=]';
}
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(s) 而不是动态分配的数组。
这是一个使用 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 = '[=12=]';
}
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 = '[=12=]';
}
if ( n1 ) printf( "Upper: %s\n", upper );
if ( n2 ) printf( "Lower: %s\n", lower );
return 0;
}
我认为您了解了大致的思路,但遗漏了一些重要的细节:
不要使用 strcat
连接两个字符串。您已经将它们中的每一个都放在了自己的缓冲区中另外,如果您要这样做,您最好确保您有足够的内存来容纳更大的结果字符串。
if (s1[i]>=65 && s1[i] <= 90)
这个条件可以很好地检查大写字母,但它的否定会给你留下其他一切,包括小写字母、数字等。所以最好有 3大小写(大写,小写,其他所有)只是为了安全起见)。
如果您要打印 upper/lower 数组的内容,请确保附加 '[=13=]'
字符,以便打印函数将它们解释为字符串。
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] = '[=10=]';
upper[k] = '[=10=]';
//print the result
printf ("Upper: %s\n", upper);
printf ("Lower: %s\n", lower);
这应该可以完成工作。
您还有一个问题:如果输入超过23个字符的字符串会怎样?你的程序会崩溃。
如果最大长度为 25 个字符,则您的数组的尺寸必须为 26,而不是 25,以说明终止 NULL。
那么为了安全起见,你必须设置s1[N-1]='\0'和s2[N-1] = '\n'。
如果您为第一个字符串输入的内容太长,第二个字符串最终将成为剩余字符,忽略您在第二个字符串提示后输入的任何内容。
我正在为即将到来的考试做练习题,但似乎无法弄清楚 objective 是:
编写一个 C 程序来读取两个字符串 s1
和 s2
。每个字符串的最大长度为 25。形成两个新的字符串,称为 upper
和 lower
。 Lower 由 s1
和 s2
的小写字母串联而成,而 upper
包含两个字符串的大写字母的串联。
例如: 输入:
s1: GREENblue
s2: busCAR
输出:
upper: GREENCAR
lower: 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);
}
在您的代码中,在 strcat()
strcat (s1, s2);
s1
可能没有足够的内存来保存连接的字符串。在这种情况下,它会调用 undefined behaviour.
来自手册页,
If
dest
is not large enough, program behavior is unpredictable; buffer overruns are a favorite avenue for attacking secure programs.
根据您的要求
The maximum size of each string is 25
您需要一个长度为 25 X 2(对于 char
s)+ 1(对于 null)的目标缓冲区。
此外,它表明,您需要 s1
和 s2
来包含 26
个元素,每个元素都用于容纳 null。
根据您的要求,您的程序需要进行某些设计更改,因为
您需要
s1
和s2
具有26
个元素,每个元素都用于容纳 null。upper
和lower
的大小都必须是输入大小的总和。想想s1
和s2
都完全大写(或小写)的场景。所以,你需要upper[51]
和lower[51]
.
这是我目前的情况::)
#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 = '[=10=]';
}
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 = '[=10=]';
}
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(s) 而不是动态分配的数组。
这是一个使用 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 = '[=12=]';
}
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 = '[=12=]';
}
if ( n1 ) printf( "Upper: %s\n", upper );
if ( n2 ) printf( "Lower: %s\n", lower );
return 0;
}
我认为您了解了大致的思路,但遗漏了一些重要的细节:
不要使用
strcat
连接两个字符串。您已经将它们中的每一个都放在了自己的缓冲区中另外,如果您要这样做,您最好确保您有足够的内存来容纳更大的结果字符串。if (s1[i]>=65 && s1[i] <= 90)
这个条件可以很好地检查大写字母,但它的否定会给你留下其他一切,包括小写字母、数字等。所以最好有 3大小写(大写,小写,其他所有)只是为了安全起见)。如果您要打印 upper/lower 数组的内容,请确保附加
'[=13=]'
字符,以便打印函数将它们解释为字符串。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] = '[=10=]'; upper[k] = '[=10=]'; //print the result printf ("Upper: %s\n", upper); printf ("Lower: %s\n", lower);
这应该可以完成工作。
您还有一个问题:如果输入超过23个字符的字符串会怎样?你的程序会崩溃。
如果最大长度为 25 个字符,则您的数组的尺寸必须为 26,而不是 25,以说明终止 NULL。
那么为了安全起见,你必须设置s1[N-1]='\0'和s2[N-1] = '\n'。 如果您为第一个字符串输入的内容太长,第二个字符串最终将成为剩余字符,忽略您在第二个字符串提示后输入的任何内容。