I'm going to identify the difference between two string. I can't see what I'm missing here. The output from my code is correct by the sample. But when I test run it with other test, it fails. I can't see what the other tests are.
The input:
The first line of input contains an integer 1<= n <= 500, indicating the number of test cases that follow. Each test case is a pair of lines of the same length, 1 to 50 characters. Each string contains only letters (a-z,A-Z) or digits (0-9).
The Output:
For each test case, output the two lines in the order they appear in the input. Output a third line indicating similarities and differences as described above. Finally, output a blank line after each case.
Sample:
int main()
{
int n;
// scan the integer for number of test cases
if(scanf("%d", &n) != 1) {
return 1;
}
//Loop through the test cases
for (int i = 0; i < n; i++)
{
char string1[1024], string2[1024], output[50];
//Scan first and second string
if(scanf("%s", string1) != 1) {
return 1;
}
if(scanf("%s", string2) != 1) {
return 1;
}
//Loop through the strings and compare them
for (int i = 0; string1[i] != '\0' || string2[i] != '\0'; i++)
{
//Convert to lowercase
string1[i] = tolower(string1[i]);
string2[i] = tolower(string2[i]);
//Compare
if (string1[i] == string2[i])
{
output[i] = '.';
} else {
output[i] = '*';
}
}
//Print the strings and the output.
printf("%s\n%s\n%s\n", string1, string2, output);
if(i + 1 < n) {
printf("\n");
}
}
return 0;
}
Maybe the problem is that when you have an input string in upper case ("ABCD") you print it in lowercase in the output ("abcd")?
The output string is never terminated, a '\0' should be added after the loop is over, otherwise printf would read over to the memory filled by previous test cases if their inputs were longer.
There is no great sense to declare the variable n as having the signed integer type int. Declare it at least as having type unsigned int.
unsigned int n;
// scan the integer for number of test cases
if(scanf("%u", &n) != 1) {
return 1;
}
The three character array should be declared as having 51 elements
char string1[51], string2[51], output[51];
The calls of scanf will look like
//Scan first and second string
if(scanf(" %50s", string1) != 1) {
return 1;
}
if(scanf(" %50s", string2) != 1) {
return 1;
}
Also you need to check that the entered strings have the same length as for example
if( strlen( string1) != strlen( string2 ) ) {
return 1;
}
This for loop
for (int i = 0; string1[i] != '\0' || string2[i] != '\0'; i++)
can invoke undefined behavior if the lengths of strings are not equal each other. If you will include the above shown if statement then the for loop can look the following way
size_t i = 0;
for ( ; string1[i] != '\0'; i++ )
These statements change the original strings
//Convert to lowercase
string1[i] = tolower(string1[i]);
string2[i] = tolower(string2[i]);
that you should not do. Just compare corresponding characters like
if (string1[i] == string2[i])
{
output[i] = '.';
} else {
output[i] = '*';
}
If you want to compare characters independent on their cases then write
if ( tolower( ( unsigned char )string1[i] ) == tolower( ( unsigned char )string2[i] ) )
{
output[i] = '.';
} else {
output[i] = '*';
}
After the for loop write
output[i] = '\0';
tp form a string in the array output.
It seems this if statement
if(i + 1 < n) {
printf("\n");
}
is redundant. Just output the new line character '\n'
putchar( '\n' );
after each test case.
Needlessly complicated. And, if the source strings contain any whitespace characters, scanf won't satisfy your needs. Below is both simpler and more robust.
Challenge assures no line more than 50 (or 500???) chars, so use only two small arrays.
Challenge is to also output LF after EVERY test case, so suppressing final one with special code is wrong.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
void readAline( char *p, size_t n ) { // do or die
if( fgets( p, n, stdin ) == NULL )
exit( 1 );
}
int mmain() {
char buf[2][ 50 + 1 + 1 ]; // +2 = up to 50 + LF + '\0' from fgets()
readAline( buf[0], sizeof buf[0] );
int n = atoi( buf[0] );
while( n-- ) {
readAline( buf[0], sizeof buf[0] );
readAline( buf[1], sizeof buf[1] );
// can't be too careful when dealing with input
assert( strlen( buf[0] ) == strlen( buf[ 1 ] ) );
printf( "%s%s", buf[0], buf[1] ); // echo to stdout
// source data defined "up to 50 chars, so no test for '\0'
// recycle buf[0] for output
for( int i = 0; buf[0][i] != '\n'; i++ )
buf[0][i] = buf[0][i] == buf[1][i] ? '.' : '*';
puts( buf[0] ); // uses loaded LF and appended LF
}
return 0;
}
Demonstration
1
the cat sat on the mat
the fat cat in the vat
the cat sat on the mat // here is the echo
the fat cat in the vat
....*...*...*......*.. // here is the analysis
// blank line
Related
void camelCase(char* word)
{
/*Convert to camelCase*/
int sLength = stringLength(word);
int i,j;
for (int i = 0; i < sLength; i++){
if (word[i] == 32)
word[i] = '_';
}
//remove staring char '_',*,numbers,$ from starting
for (i = 0; i < sLength; i++){
if (word[i] == '_'){
word[i] = toUpperCase(word[i + 1]);
}
else
word[i] = toLowerCase(word[i]);
}
word[0] = toLowerCase(word[0]);
//remove any special chars if any in the string
for(i = 0; word[i] != '\0'; ++i)
{
while (!((word[i] >= 'a' && word[i] <= 'z') || (word[i] >= 'A' && word[i] <= 'Z') || word[i] == '\0') )
{
for(j = i; word[j] != '\0'; ++j)
{
word[j] = word[j+1];
}
word[j] = '\0';
}
}
}
int main()
{
char *wordArray;
wordArray = (char*)malloc(sizeof(char)*100);
// Read the string from the keyboard
printf("Enter word: ");
scanf("%s", wordArray);
// Call camelCase
camelCase(wordArray);
// Print the new string
printf("%s\n", wordArray);
return 0;
}
I am writing a function that takes in this for example _random__word_provided, and I am to remove any additional underscores or special characters, capitalize the first word after an underscore and reprint the word without any underscores. The above example would come out like this randomWordProvided.
When I run my code though this is what I am getting rrandomWwordPprovided. I am unsure where my loop is having issues. Any guidance would be appreciated. Thank you!
You are WAY over-processing the string...
First measure the length. Why? You can find the '\0' eventually.
Then convert ' 's to underscores (don't use magic numbers in code).
Then force almost everything to lowercase.
Then try to "strip out" non-alphas, cajoling the next character to uppercase.
(The non-alpha '_' has already been replaced with an uppercase version of the next character... This is causing the "thewWho" duplication to remain in the string. There's no indication of '$' being addressed as per your comments.)
It seems the code is traversing the string 4 times, and the state of the string is in flux, leading to hard-to-understand intermediate states.
Process from beginning to end in one pass, doing the right thing all the way along.
char *camelCase( char word[] ) { // return something usable by the caller
int s = 0, d = 0; // 's'ource index, 'd'estination index
// one sweep along the entire length
while( ( word[d] = word[s] ) != '\0' ) {
if( isalpha( word[d] ) ) { // make ordinary letters lowercase
word[ d ] = tolower( word[ d ] );
d++, s++;
continue;
}
// special handling for non-alpha. may be more than one!
while( word[s] && !isalpha( word[s] ) ) s++;
// end of non-alpha? copy alpha as UPPERCASE
if( word[s] )
word[d++] = toupper( word[s++] );
}
// make first character lowercase
word[ 0 ] = tolower( word[ 0 ] );
return word; // return modified string
}
int main() {
// multiple test cases. Add "user input" after algorithm developed and tested.
char *wordArray[] = {
"_random__word_provided",
" the quick brown fox ",
"stuff happens all the time",
};
for( int i = 0; i < 3; i++ )
puts( camelCase( wordArray[i] ) );
return 0;
}
randomWordProvided
theQuickBrownFox
stuffHappensAllTheTime
There may come comments pointing out that the ctype.h functions receive and return unsigned datatypes. This is a "casting" elaboration that you can/should add to the code if you ever expect to encounter something other than 7-bit ASCII characters.
In my opinion, there's a very simple algorithm that just requires you to remember the last character parsed only:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
void camelCase(char* source)
{
/*Convert to camelCase*/
char last = '_',
*dest = source;
/* while we are not at the string end copy the char values */
while ((*dest = *source++) != '\0') {
/* if the char is a lower case letter and the previous was a '_' char. */
if (islower(*dest) && last == '_')
*dest = toupper(*dest);
/* update the last character */
last = *dest;
/* to skip on the underscores */
if (*dest != '_') dest++;
}
} /* camelCase */
int main()
{
char wordArray[100]; /* better use a simple array */
// Read the string from the keyboard
printf("Enter identifiers separated by spaces/newlines: ");
/* for each line of input */
while (fgets(wordArray, sizeof wordArray, stdin)) {
for ( char *word = strtok(wordArray, " \t\n");
word;
word = strtok(NULL, " \t\n"))
{
printf("%s -> ", word);
// Call camelCase
camelCase(word);
// Print the new string
printf("%s\n", word);
}
}
return 0;
}
if you actually want to skip the first character (and don't convert it to uppercase), you can initialize last with a different char (e.g. '\0')
#include <stdio.h>
#include <string.h>
int main(){
char c[20], result[50];
int bool = 0, count = 0, i;
while(fgets(c,20,stdin) != NULL){
int stringSize = strlen(c);
if(stringSize == 11){
int ascii = (int)(c[i]);
for(i = 0; i < stringSize; i++){
if(ascii >= 'A' && ascii <= 'Z'){
bool = 1;
}
}
}
}
if(bool == 1){
count++;
strcat(result,c);
}
printf("%d", count);
printf("%s",result);
}
Good morning, I am fairly new to programming, and I've spent quite a while Googling and searching around for this issue already, but I can't seem to wrap my head about it.
Basically I'm trying to filter an fgets so that it reads each string, and if they're capital letters, they're "valid". However, I can't even get the fgets to stop accepting more input.
Edit: The idea is to store in result every String that has 10 capital letters, and for the fgets while loop to break once the user gives no input ('\0')
If you are entering strings from the standard input stream then it is better to rewrite the condition of the while loop the following way
while( fgets(c,20,stdin) != NULL && c[0] != '\n' ){
In this case if the user just pressed the Enter key without entering a string then the loop stops its iterations.
Pay attention to that fgets can append the new line character '\n' to the entered string. You should remove it like
c[ strcspn( c, "\n" ) ] = '\0';
Then you could write
size_t n = strlen( c );
if ( n == 10 )
{
size_t i = 0;
while ( i != n && 'A' <= c[i] && c[i] <= 'Z' ) ++i;
bool = i == 10;
}
Pay attention to that it is a bad idea to use the name bool because such a name is introduced as a macro in the header <stdbool.h>.
Also it seems this if statement
if(bool == 1){
count++;
strcat(result,c);
}
must be within the while loop. And the array result must be initially initialized
char c[20], result[50] = { '\0' };
Everything is working in my code but as soon as user inputs "BYE" my program is not ending i don't know why while loop is not responding to that code
#include "stdio.h"
#include <string.h>
int main(void)
{
char ch[20];
while (ch != "bye")
{
scanf("%s", ch);
int i;
int n = strlen(ch);
int c = 0;
for (i = 0; i < n / 2; i++)
{
if (ch[i] == ch[n - i - 1])
c++;
}
if (c == i)
{
printf("1");
}
else
{
printf("0");
}
}
return 0;
}
For starters the array ch was not initialized that is initially it does not contain a string
char ch[20];
Secondly in the condition of the while loop
while (ch != "bye")
there are compared two addresses: the address of the first element of the array ch and the address of the first element of the string literal "bye". As the array and the string literal occupy different extents of memory the addresses always will be unequal. So as a result you have an infinite loop that does not contain a break statement.
If you want to compare strings then you need to use the standard string function strcmp as for example
if ( strcmp( ch, "bye" ) == 0 )
{
//...
}
In this case the array ch shall already contain a string.
So instead of the while statement it is better to use do-while statement or an infinite while statement that will be interrupted through the break statement if strcmp will return 0.
For example
while ( 1 )
{
char ch[20];
scanf("%19s", ch );
if ( strcmp( ch, "bye" ) == 0 ) break;
size_t n = strlen(ch);
size_t i = 0;
while ( i < n / 2 && ch[i] == ch[n - i - 1] ) ++i;
if ( i == n / 2 )
{
printf("1");
}
else
{
printf("0"); }
}
}
I am trying to find the no of lower and uppercase characters from a input.
here's my code:
#include <stdio.h>
#include <string.h>
int main()
{
char cAFirst[25];
int k = 0,uc =0 ,lc =0 ;
fgets(cAFirst,25,stdin);
// printf("out: %d \n",k);
for (size_t i = 0; i < 25; i++) {
k = (int)cAFirst[i];
if ((k <= 90) && (k >= 65)) {
uc++;
}
if ((k >= 97) && (k <= 122)) {
lc++;
}
}
printf("Uppercase Letters=%i \nLowercase Letters=%i \n",uc,lc );
return 0;
}
lowercase (lc) is ok, but value of uc is randomly incremented.
I have already tried changing formatting of printf and it sometimes work, but problem is i have to submit this code with same formatting given above.
Rather then always iterate 25 times, iterate until the end of input is detected.
// for (size_t i = 0; i < 25; i++) {
for (size_t i = 0; cAFirst[i]; i++) { // detect null character.
Considering this snippet from OP's posted code:
char cAFirst[25]; // <- Uninitialized, the contents are indeterminated
// ...
fgets(cAFirst,25,stdin); // <- We don't know if it succeeded or not
// ...
for (size_t i = 0; i < 25; i++) {
// ... ^^^^^^
}
It copies up to 24 chars from stdin to the array (including the newline, if present), also adding the null-terminator (if no stream error occurred), but when the loop is executed, it goes over all the 25 char of the array, even if the inputted string is shorter, taking into account chars with indeterminate value.
To avoid this, we just have to test only the characters which were actually read from the input stream, by counting them or using the null-terminator as a sentinel.
We could intialize the array (to zero) and also avoid the use of repeated magic numbers, which is error prone.
#include <stdio.h>
// I'd use a bigger value, like 256, but OP's use case is not specified.
enum {
BUF_SIZE = 25
};
int main(void)
{
// All the elements of the array are set to zero, not only the first.
char buf[BUF_SIZE] = {'\0'};
// ...
Now, even if all the chars in the array are tested in the previous loop, there won't be spurious values and the statistics will be consistent. This is not a real solution, though, and while it is commonly suggested to initialize all the variables before their use, in this case it is not necessary.
As noted by chux, the return value of functions like fgets should be checked, to verify that the operation has succeeded and that our variables are in a valid state.
if ( fgets(buf, BUF_SIZE, stdin) == NULL ) {
if (feof(stdin)) {
fprintf(stderr, "Abnormal end of input.\n");
// The contents of the array are not altered
}
if (ferror(stdin)) {
fprintf(stderr, "A stream error occurred.\n");
// The contents of the array are indeterminated, maybe not even null-terminated
}
exit(EXIT_FAILURE);
}
The key point is to be sure that, after this call, the array is null-terminated. Even a check like the following could be enough:
if ( fgets(buf, BUF_SIZE, stdin) == NULL ) {
fprintf(stderr, "An error occurred while reading from stdin.\n");
buf[0] = '\0';
// Continues the program despite the error, but with a valid (empty) string
}
It's worth remembering that any further characters besides the ones read, remain in the input stream.
Now that we have a valid (null-terminated) array, we can loop through it:
int uc = 0, lc = 0;
for (size_t i = 0; buf[i] != '\0'; i++) {
// which can also be written as 'for (size_t i = 0; buf[i]; i++) {'
// It's also more readable without magic numbers:
if ( 'A' <= buf[i] && buf[i] <= 'Z' ) {
uc++;
}
else if ( 'a' <= buf[i] && buf[i] <= 'z' ) {
lc++;
}
}
printf("Uppercase Letters = %i\nLowercase Letters = %i\n", uc, lc);
return EXIT_SUCCESS;
}
The previous snippet may be generalized from ASCII codes using functions like isupper and islower defined in header <ctype.h>. Also, the actual length of the string can be used to limit the for-loop:
// Length of the maximum initial segment of the array, that consists of
// only the characters not equal to a newline or null character
size_t length = strcspn(buf, "\n");
int uc = 0, lc = 0;
for (size_t i = 0; i < length; i++) {
unsigned char k = buf[i];
if ( isupper(k) ) {
uc++;
}
else if ( islower(k) ) {
lc++;
}
}
// ...
You should first use a way to iterate your string only once maybe a while loop and try to read not just what you need but also what there could be which should not be counted. What happens if there is \t or \n Do you need them to count too?
Here is an approach which can help you to understand that:
#include <stdio.h>
int main( void )
{
char string[] = "AbcDEfgHiJKlmnOPqrstUVWxyZ\n§$%$§";
int uc, lc, i, others;
uc = lc = i = others = 0;
while ( string[i] )
{
if ( string[i] >= 'A' && string[i] <= 'Z' )
{
uc++;
}else if ( string[i] >= 'a' && string[i] <= 'z' ){
lc++;
}else{
others++;
}
i++;
}
if ( i == ( lc + uc + others ) )
{
printf( "OK\n\n" );
printf("Uppercase Letters = %i \nLowercase Letters = %i \nOthers = %d \n", uc, lc, others );
printf("Total = %d\n", i );
}else
{
printf("Something went Wrong.\n\n");
}
}
Your if/else statements could be easy replaced by the functions isupper( string[i] ) and islower( string[i] ) which are found in ctype.h
if ( isupper( string[i] ) )
{
uc++;
}else if ( islower( string[i] ) )
{
lc++;
}else{
others++;
}
I am blocked at solving a problem in the book.
The problem is:
read a word and output the string backwards, and output it backwards,
you should print the palindrome if it is the same as the original.
Also, do not use a library such as string.h, but include stdio.h
only.
So I created the code below.
#include <stdio.h>
int main()
{
char str[128];
char temp;
int leng = 0;
char a;
scanf("%s", str);
{
a = str;
}
while(str[leng] != '\0')
leng++;
for (int i = 0; i < leng/2; i++)
{
temp = str[i];
str[i] = str[leng - i - 1];
str[leng - i - 1] = temp;
}
printf("%s\n", str);
{
if (a == str)
printf("palindrome\n");
}
return 0;
}
The output in reverse order was easily solved, but I blocked in the process at printing palindrome. I tried to print the palindrome only when the input and output values are the same.
However, if (a == str) I used was a code to compare address values.
Also,I thought that it would be useful to implement strcmp as a loop, but I can not find a way to compare the input value with the output value using strcmp.
Is there a way to compare the input and output values in C? Or is there a way to make palindrome print only under certain circumstances (input = output)?
I am wondering if I can code the input value = output value in C exactly.
Note that my code prints the palindrome when the address values are the same. So I haven't seen yet :(
Here is a loosely written untested code that should resolve your issues.
char str[128];
if( fgets( str, 128, stdin ) )
{
/* I hate this but restriction on string.h
Calculate the size of this string */
size_t s_len = 0;
char *p = str;
for( ; *p && *p != '\n' ; p++ )
s_len++;
/* trim down nextLine characters */
if( p && *p == '\n' )
{
*p = '\0';
}
if( s_len == 0 )
{
/* Should never be the case here */
exit(0);
}
/* This should handle both cases of reversing and pallindrom */
int isPallindrom = 1; /* Lets Say Yes for now*/
for( size_t i = 0, j = s_len-1; i < j ; i ++, j -- )
{
if( str[i] != str[j] )
isPallindrom = 0; // Not a pallindrom
swap( str, i, j); // Write a swap function here
}
/* at this point you should have
1. a reversed string in a
2. based on isPallindrom value a confirmation if it really a pallindrom */
}
There are some fundamental errors in your code for instance
a = str;
if (a == str)
turn on warnings while compilation to catch these well before execution.
edit - swap for you.
void swap( char *s, size_t i, size_t j )
{
char t = s[i];
s[i] = s[j];
s[j] = t;
}
Use this function:
int compare(char *str1, char *str2)
{
while(*str1 && *str2){
if(*str1 == *str2){
str1++;
str2++;
}
else return (*str2 - *str1);
}
if(*str1)
return -1;
if(*str2)
return 1;
return 0;
}
Logic:
Until '\0' is encountered in one of the strings, check the character in either string. If the characters are equal, continue. Otherwise, return a negative number of the character in string1 > string2, or a positive number if the character in string1 < string2.
Once a '\0' is encountered, check if string1 has any more characters. If yes, it is the greater string, hence return a negative number.
If string1 doesn't have any more characters, check string2. If that too has no more characters, return 0. Otherwise return a positive number.