Reputation: 29
This is my program (school exercise, should be receiving a string from the user, change it and return the original and new string in a certain format):
#include <stdio.h>
#define MAX_STRING_LENGTH 50
char switchChar(char c) {
if ((c >= 'A') && (c <= 'Z')) {
c = c + 32;
} else
if ((c >= 'a') && (c <= 'z')) {
c = c - 32;
}
if ((c > '5') && (c <= '9')) {
c = 56;
}
if ((c >= '0') && (c < '5')) {
c = 48;
}
return c;
}
int main(void) {
char temp;
int i = 0;
char stringInput[MAX_STRING_LENGTH + 1];
printf("Please enter a valid string\n");
fgets(stringInput, 50, stdin);
char newString[MAX_STRING_LENGTH + 1];
while ((i != MAX_STRING_LENGTH + 1) && (stringInput[i] != '\0')) {
temp = switchChar(stringInput[j]);
newString[i] = temp;
i++;
}
printf( "\"%s\"", stringInput);
printf("->");
printf( "\"%s\"", newString);
return 0;
}
When running, the output goes down a line after the string and before the last "
character, although it should all be printed in the same line.
I would appreciate any directions.
Upvotes: 1
Views: 317
Reputation: 144540
There are several issues in your code:
fgets()
reads and leaves the newline character at the end of the destination array if present and if enough space is available. For consistency with your algorithm, you should strip this newline. You can do this safely with stringInput[strcspn(stringInput, "\n")] = '\0';
or use a little more code if you cannot use <string.h>
. The presence of this newline character explains the observed undesirable behavior.
You read a line with fgets()
, but you pass a buffer size that might be incorrect: hard coded to 50
when the array size is MAX_STRING_LENGTH + 1
. With MAX_STRING_LENGTH
defined as 50
, it is not a problem, but if you later change the definition of the macro, you might forget to update the size argument to fgets()
. Use sizeof stringInput
for consistency
you forget to set the null terminator in newString
. Testing the boundary value for i
is not necessary as stringInput
is null terminated within the array boundaries.
in switchChar()
, you should not hardcode character values from the ASCII charset: it reduces portability and most importantly, reduces readability.
Here is a corrected and simplified version:
#include <stdio.h>
#define MAX_STRING_LENGTH 50
char switchChar(char c) {
if ((c >= 'A') && (c <= 'Z')) {
c = c + ('a' - 'A');
} else
if ((c >= 'a') && (c <= 'z')) {
c = c - ('a' - 'A');
} else
if ((c > '5') && (c <= '9')) {
c = '8';
} else
if ((c >= '0') && (c < '5')) {
c = '0';
}
return c;
}
int main(void) {
char stringInput[MAX_STRING_LENGTH + 1];
char newString[MAX_STRING_LENGTH + 1];
int c;
printf("Please enter a valid string\n");
if (fgets(stringInput, sizeof stringInput, stdin) != NULL) {
// strip the newline character if present
//stringInput[strcspn(stringInput, "\n")] = '\0';
char *p;
for (p = stringInput; *p != '\0' && *p != '\n'); p++)
continue;
*p = '\0';
for (i = 0; stringInput[i] != '\0'; i++) {
newString[i] = switchChar(stringInput[i]);
}
newString[i] = '\0';
printf("\"%s\"", stringInput);
printf("->");
printf("\"%s\"", newString);
printf("\n");
}
return 0;
}
Upvotes: 3
Reputation: 148870
You requirements contain:
In that case, scanf
is probably more adapted than fgets
, because the former will clean the input for any initial blank(space or tab) and stop before the first trailing blank (space, tab, cr or newline). Remark: as scanf
stops before the first blank, the string cannot contains spaces or tab. If it is a problem, use fgets
.
Just replace the line:
fgets(stringInput, 50, stdin);
with:
i = scanf("%50s", stringInput);
if (i != 1) { /* always control input function return code */
perror("Could not get input string");
return 1;
}
If you prefere to use fgets
for any reason, you should remove the (optional) trailing newline:
if (NULL == fgets(stringInput, 50, stdin)) { /* control input */
perror("Could not get input string");
return 1;
}
int l = strlen(stringInput);
if ((l > 0) && (stringInput[l - 1] == '\n')) { /* test for a trailing newline */
stringInput[l - 1] = '\0'; /* remove it if found */
}
Upvotes: 0
Reputation: 121347
It's because fgets()
reads in the newline character as well if there's room in the buffer and it's stored in your newString
.
You can remove it with:
fgets(stringInput,50,stdin);
stringInput[strcspn(stringInput, "\n")] = 0; /* removes the trailing newline if any */
From fgets()
:
fgets() reads in at most one less than size characters from stream and stores them into the buffer pointed to by s. Reading stops after an EOF or a newline. If a newline is read, it is stored into the
buffer. A terminating null byte ('\0') is stored after the last character in the buffer.
Upvotes: 1