Weird string appends on printf - c

I wrote a simple program to toggle string, I tried in my computer and IDEOne, I am receiving a weird string appended to the output. Am I missing something?
#include <stdio.h>
int main (int argc, char *argv[]) {
char input[100], output[100];
int length;
scanf("%s", input);
length = sizeof(input)/sizeof(input[0]);
for (int i = 0; input[i] != '\0'; i++) {
if (input[i] >= 97 && input[i] <= 122) {
output[i] = input[i] - 32;
} else if (input[i] >= 65 && input[i] <= 90) {
output[i] = input[i] + 32;
}
}
printf("%s\n", output);
return 0;
}
Link to IDEOne - https://ideone.com/NFlDJK

%s expects a null terminated string as an argument. You have to append a '\0' character at the end of output.

You don't terminate your output, i.e. you do not write the final \0-character that marks the end of a string. Hence, printf, which expects a 0-terminated string, probably prints some garbage. A simple solution would be to define output as
char output[100] = { 0 };
Thereby, output will be filled with \0 and anything you write in before will find some end then.
As pointed out in the comments, there are some more issues in the code which may lead to undefined behaviour or unexpected results.
First, you'll get a buffer overflow if you enter more than 99 characters (then yielding undefined behaviour). You could avoid this by using scanf("%99s", input).
Second, you may get an unexpectedly short result if your input contains some characters not triggering your toggle-expression. In your code, output would contain garbage at the relevant position; in the output = { 0 }-variant, the result would "end" at this point. Hence, an input like "abc1234DEF" might yield "ABC?#:-def"or "ABC", respectively. Add an else { output[i]=input[i]; } to overcome this.
Third, length = sizeof(input)/sizeof(input[0]) will always return 100, regardless of the actual number of characters entered. Note that sizeof(input) will be 100 and sizeof(input[0]) will 1 as compile time constants. To get the "length" of the string in terms of number of characters entered use strlen(input).
int main (int argc, char *argv[]) {
char input[100], output[100] = { 0 };
scanf("%99s", input);
size_t length = strlen(input);
for (int i = 0; i < length; i++) {
if (input[i] >= 97 && input[i] <= 122) {
output[i] = input[i] - 32;
} else if (input[i] >= 65 && input[i] <= 90) {
output[i] = input[i] + 32;
}
else {
output[i] = input[i];
}
}
printf("%s\n", output);
return 0;
}

the answer to the question is:
the output[] array must be NUL (0x00) terminated.
The '%s" format specifier in the call to printf() does not stop outputting bytes until it encounters a NUL.
Since the posted code failed to set the needed NUL byte, the "%s" will keep outputting bytes until it happens upon some random NUL byte.
This is undefined behavior and can lead to a seg fault event.
You can fix the problem by:
after the for() code block and before the printf() statement, insert the statement:
output[i] = '\0';

After your loop i is one more i.e you just have to put
Output[i]='\0';
And its done

Related

How to modify the characters in a char array

My intention was to use the command line to read input and store it into an array and modify the characters of the array. If the character is '1', then turn it into '0', vice versa. I successfully store the input into an array, yet failed to modify the characters of the array. If I put 0000000000000000000000000000000(32bits) into my program, the output doesn't change.
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]) {
char *a = argv[argc-1];
char arr[33];
size_t length = strlen(a);
for(size_t i=0;i<length;i++) {
arr[i]=a[i];
}
for(int j=0; j<32;j++) {
if(arr[j]=='0') {
arr[j]='1';
}
if(arr[j]=='1') {
arr[j]='0';
}
}
for(int k=0;k<32;k++) {
printf("%c",arr[k]);
}
}
If I put 0000000000000000000000000000000(32bits) into my program, the output doesn't change.
First of all, your program is not processing bits of input but it is processing the characters of input you are passing as command line argument to your program. If you want to process the bits of input, to start with, read about bitwise operators first.
Look at this for loop:
for(int j=0; j<32;j++) {
if(arr[j]=='0') {
arr[j]='1';
}
if(arr[j]=='1') {
arr[j]='0';
}
}
If current processing arr element value is '0', the second if condition in the for loop body will nullify the effect of first if condition on that arr element i.e. the arr element value will be unchanged and if the current processing arr element value is '1' than it will be set to '0'. So, after the loop, all the elements of array arr, which have original value as either '1' or '0', will set to '0' and that's the flaw in your logic.
Few suggestions:
If program is supposed to receive command line argument('s), make sure to put check on argc value. In your case, user is supposed to pass the string comprised of '0's and '1's, so you should check on argc value, something like:
if (argc != 2) {
printf ("Usage: <exe_name> <string_of_0s_and_1s>\n");
return 1;
}
Since, you do not have check on argc value in your program, if user do not pass any string from command line, the value of argc may be 1 and ,in this case, argv[argc-1] (or argv[0]) represents the program name or if the program name is not available from the host environment than argv[0][0] will be the null character. If argv[0] represents program name whose length is greater than 32 characters then your program will land up in undefined behaviour territory because there is no check on whether the command line input string length is <= 32 characters while copying it to arr buffer.
Since you are copying the input to char array (not as string) declare arr as array of 32 characters and not 33 characters. Looks like, you have assumed the input will be of size <= 32 characters. There is no problem with this assumption as long as program is running in a controlled environment where you are taking care of it. But still, by chance, if input string length is > 32 characters then your program behaviour will be undefined as it will end up processing array arr beyond it's size. You should add a check on length of input string as well:
if (length > 32) {
printf ("Input string length is >= 33 character.\n" \
"The permitted input string length is <= 32 characters.\nExiting..\n");
return 1;
}
If you want the input string to be of exact 32 characters, you can add check if (length != 32).
While copying the string, you can also add check on the characters of input string and if it contain character other than '1' and '0' then throw error message and exit.
Putting these altogether :
#include <stdio.h>
#include <string.h>
int main (int argc, char *argv[]) {
char *a = NULL;
char arr[32];
if (argc != 2) {
printf ("Usage: <exe_name> <string_of_0s_and_1s>\n");
return 1;
}
a = argv[argc-1];
size_t length = strlen(a);
if (length > 32) {
printf ("Input string length is > 32 characters.\n" \
"The permitted input string length is <= 32 characters.\nExiting..\n");
return 1;
}
for (size_t i = 0; i < length; i++) {
if ((a[i] != '1') && (a[i] != '0')) {
printf ("Found a character other than characters '1' and '0' in the input string.\n" \
"The input string should comprised of characters `1' and '0' only.\nExiting..");
return 1;
}
arr[i] = a[i];
}
for (size_t j = 0; j < length; j++) {
if (arr[j] == '0') {
arr[j] = '1';
} else {
arr[j] = '0';
}
}
for (size_t k = 0; k < length; k++) {
printf ("%c", arr[k]);
}
return 0;
}
you forget to give an else if condition in this part of the code.
for(int j=0; j<32;j++) {
if(arr[j]=='0') {
arr[j]='1';
}
else if(arr[j]=='1') { //This part should be else if
arr[j]='0';
}
}
In your code for the value of 0 it changed to 1. But for another if condition the value changed to 0 again.
To copy string you need to copy null character as well.
size_t length = strlen(a);
14 for(size_t i=0;i<=length;i++){
15 arr[i]=a[i];
But you do not need to traverse the string twice
size_t i=0;
while((arr[i]=a[i])) i++;
Your if is wrong. It should be
if(arr[j]=='0') arr[j]='1';
else arr[j]='0';

Why does the output have random characters at the end?

I was trying to solve a problem in toph.co platform. I have made a code. It is not working as it should be. Giving me the correct output in some cases. But when I am trying a case with 'o' it is entering in a loop. And maybe the problem is there. But I am unable to find that out.
Problem link: https://toph.co/p/better-passwords
Please help me to solve the problem in my code. I am using c programming language. As I am new in programming, I am not getting the point that is wrong.
I have tried it in many ways. Modifying the code again and again. Now I am becoming mad.
#include <stdio.h>
#include<string.h>
int main()
{
char s[40], i, j;
int len;
gets(s);
len= strlen(s);
for(i=0; i<=len; i++)
{
if(s[i] == 's')
{
s[i]= '$';
}
else if(s[i] == 'i')
{
s[i]= '!';
}
else if(s[i] == 'o')
{
s[i]= '(';
for(j=len; j>i; j--)
{
s[j]=s[j-1];
len= strlen(s);
}
s[i+1]=')';
}
else
{
continue;
}
len= strlen(s);
}
if (s[0]>='a' && s[0]<='z')
{
s[0]= s[0]- 32;
}
int new_len=strlen(s);
s[new_len]='.';
puts(s);
return 0;
}
I expect the output Un$()ph!$t!cated. , but it is showing Un$()ph!$t!cated.....'Many unwanted charecter'.....
Your string null byte is missing after manipulations, easiest way to avoid such problems - is to initialize whole character array into zero bytes:
char s[40] = {0}, // was char s[40], uninitialized !
Also do you notice a compile message "warning: the `gets' function is dangerous and should not be used" ?
gets() is dangerous, because it is not protected from buffer overflow - try to run your program with very long string exceeding your buffer s capacity and you will get a crash :
* stack smashing detected *: terminated Aborted (core dumped)
Use fgets() instead of gets(), like so :
fgets(s, 39, stdin);
if (s[strlen(s)-1] == '\n') s[strlen(s)-1] = '\0'; // deleting newline character
Notice, that we read here BUFFER_SIZE - 1 characters here, i.e.- by 1 char less, than your buffer is able to hold (40), because if we enter long string which is of full buffer size,- then your code extending string will smash stack once again. You need to be serious about buffer overflows.
As most commentators wrote: you don't put the end-of-string character '\0' behind the extended string. Strings in C are marked by this extra character at the end. It is needed to find the end of a string.
Example: A string "abc" is actually a sequence of 4 characters, 'a', 'b', 'c', and '\0'. Its length is 3, and its s[3] contains '\0'.
Your loop:
for(j=len; j>i; j--)
{
s[j]=s[j-1];
len= strlen(s);
}
In the first turn of the loop the character at s[len] is replaced by the character at s[len-1]. This overwrites the original '\0' with the last (visible) character of your string.
If you change the loop into:
for (j = len; j > i; j--)
{
s[j + 1] = s[j];
}
the '\0' will be copied in the first run.
Note 1: Move the assignment to len behind the loop.
Note 2: Make sure that your variable s is big enough for all inputs.
Note 3: See the whitespace I use? Adopt a good code style and stick to it.
There are a couple of places in your code where you are overwriting the "\0".
These are:
s[j]=s[j-1];
And
s[new_len]='.';
So the rectified code would be....
int main()
{
char s[40], i, j;
int len;
gets(s);
len= strlen(s);
for(i=0; i<=len; i++)
{
if(s[i] == 's')
{
s[i]= '$';
}
else if(s[i] == 'i')
{
s[i]= '!';
}
else if(s[i] == 'o')
{
s[i]= '(';
for(j=len+1; j>i; j--) //j needs to be one more than the length
{
s[j]=s[j-1];
len= strlen(s);
}
s[i+1]=')';
}
else
{
continue;
}
len= strlen(s);
}
if (s[0]>='a' && s[0]<='z')
{
s[0]= s[0]- 32;
}
int new_len=strlen(s);
s[new_len]='.';//add a '.'
s[new_len+1] = '\0'; //add the terminating character
puts(s);
return 0;
}

Why when my input is 8 or more characters long, symbols appear after printing the 8 character?

When I print 8 or more characters, symbols always print after the 8th character. Does anyone know what is wrong with the code and how can I fix this?
I've tried with different numbers of characters and it always happens when is more than 8 or 8.
#include <stdio.h>
int main() {
char ch = 0;
char temp[100];
int i = 0;
while (scanf("%c", &ch) == 1) {
if (ch != '\n') {
temp[i] = ch;
printf("%s", temp);
i++;
}
}
return 0;
}
My expected result is
1 12 123 123412345123456123456712345678
My actual output is
1 12 123 123412345123456123456712345678xxx
the x represent the symbols
The reason you get funny characters in the output is the temp array is not a proper C string because it is uninitialized so there is not necessarily a null byte '\0' after the ith entry set with temp[i] = ch;.
There are different ways to fix this problem:
you can initialize temp this way: char temp[100] = { 0 };
you can set the byte at temp[i+1] to '\0' in the loop.
Note also that the expected output is not 1 12 123 123412345123456123456712345678, but 112123123412345123456123456712345678 because you do not output a separator between the strings. It would be less confusing to output the strings on separate lines.
Finally scanf() will not return until the user has typed a newline because of buffering performed by the terminal driver and the standard input stream.
Here is a modified version:
#include <stdio.h>
int main() {
char ch;
char temp[100];
size_t i = 0;
while (scanf("%c", &ch) == 1 && i + 2 < sizeof(temp)) {
if (ch != '\n') {
temp[i] = ch;
temp[i + 1] = '\0';
printf("%s", temp);
i++;
}
}
return 0;
}
#chqrlie well explained and offered 2 alternatives.
3rd alternative: change format
printf("%s\n", temp) expects temp to be a string. In C, a string has a null character, else it is not a string.
Code failed to ensure a '\0' in temp[]. The result is undefined behavior (UB).
Code could use a precision to limit the number of characters printed with "%s".
// printf("%s", temp);
printf("%.*s", (int)i, temp);
"%.*s", (int)i, temp will print up to i characters or up to '\0' - which ever comes first. i is cast as (int) because printf expects an int for the precision given as an extra argument as specified by the .* before the s.
int main(void) {
char temp[100];
size_t i = 0;
while (i < sizeof temp && scanf("%c", &temp[i]) == 1 && temp[i] != '\n') {
i++;
}
printf("<%.*s>\n", (int)i, temp);
return 0;
}

Creating a toUpper function in C

I'm creating my own toUpper function in C, but keep getting a segmentation fault every time I attempt to run it. Can anyone provide me with any hints as to how to fix this problem?
int toUpper(char *str)
{
int i;
for(i=0;i< i <= strlen(str); i++) {
if(str[i] >= 97 && str[i] <= 122) {
str[i] = str[i] -32;
}
}
return(str[i]);
}
int main()
{
char string[20];
printf("Enter any string:\n");
scanf("%s", string);
char result= (char)(toUpper(string));
printf("The string in upper case is:%s\n", result);
}
You're running off the end of the string:
for(i=0;i< i <= strlen(str); i++) {
^--
e.g. a 10 char string has characters 0->9, but you're looping 0->10. Change <= to < so you stop at 9.
Plus, you haven't set any limit on your scanf, so if someone enters a 21 char string, you'll exceed the storage you've allocated the string array.
Recommend changing toUpper() to:
char *toUpper(char *str) {
size_t len = strlen(str);
size_t i;
for (i = 0; i < len; i++) {
if (str[i] >= 'a' && str[i] <= 'z') {
str[i] = str[i] - 'a' + 'A';
}
}
return str;
}
Use correct index range i < strlen(str) vs. i <= strlen(str). This is the main issue. #Marc B
Change return type. Suggested by #Weather Vane. like strcpy(), strcat()
Calculate string length once, rather than many times.
Use literals that match your goal: 'a' instead of 97. #marsh
Use size_t for index and length. That is the type return by strlen() and is the best type to use for array access. Makes a difference with huge strings, but not with these simple examples.
This code does depend on ASCII. This is often OK, but not completely portable.
Change 32 to -'a' + 'A' per #user295691
printf("The string in upper case is:%s\n", result);
result should be a char * but is a char. This is probably where your seg fault is happening. Other places include:
scanf("%s", string);
if the inputted string is longer than 19 chars, you could have problems due to string only being 20 chars long
for(i=0;i< i <= strlen(str); i++) {
if str for whatever reason doesn't have an ending 0, you could seg fault there as well.
Another major issue in the code is the for loop statement.
for(i=0;i< i <= strlen(str); i++)
^ ^
It's probably a typo, but the i < i < wont work.

How do i cycle through each letter in a string?

#include <stdio.h>
int main()
#include <stdio.h>
int main()
{
char msg[31] = {'\0'};
char encrypted[31] = {'\0'};
int key;
printf("Please enter a message under 30 characters: ");
fgets(msg, 31, stdin);
printf("Please enter an encryption key: ");
scanf("%d", &key);
int i = 0;
while (msg[i] && ('a' <= msg[i] <= 'z' || 'A' < msg[i] < 'Z'))
{
encrypted[i] = (msg[i] + key);
i++;
}
printf("%s\n", msg);
printf("%d\n", key);
printf("%s\n", encrypted);
}
Okay i've got my code to increment the characters but i don't know how to make it ignore special characters and spaces. Also how do i use % to loop back to 'a' and 'A'?
Thank you.
You just need a simple for loop:
for (int i = 0; i < 31; i++)
{
// operate on msg[i]
}
If you didn't know the length of the string to begin with, you might prefer a while loop that detects the null terminator:
int i = 0;
while (msg[i])
{
// operate on msg[i]
i++;
}
Your fgets and scanf are probably fine, but personally, I would be consistent when reading input, and fgets for it all. Then you can sscanf to get key out later.
scanf and fgets seem fine in this situation the way you've used them.
In C, a string is just an array of characters. So, you access each element using a for loop and array indexing:
for (int i = 0; i < strlen(str); i++) {
char thisChar = str[i];
//Do the processing for each character
}
You can perform arithmetic on thisChar as necessary, but be careful not to exceed 255. You might want to put a check on key to ensure it doesn't get too big.
Getting a string from scanf:
char msg[31];
scanf("%30s", msg);
OR (less efficient, because you have to fill the array with 0s first)
char msg[31] = { 0 };
scanf("%30c", msg);
Iterating a string is as easy a for loop (be sure to use c99 or c11)
int len = strlen(msg);
for(int i = 0; i < len; i++) {
char current = msg[i];
//do something
msg[i] = current;
}
"Encrypting" (i.e. ciphering) a character require a few steps
Determine if we have an uppercase character, lowercase character, or non-alphabetic character
Determine the position in the alphabet, if alphabetic.
Update the position, using the modulus operator (%)
Correct the position, if alphabetic
I could give you the code here, but then you wouldn't learn anything from doing it yourself. Instead, I encourage you to implement the cipher based on the steps I provided above.
Note that you can do things like:
char c = 'C';
char e = 'E' + 2;
char lower_c = 'C' - 'A' + 'a';

Resources