Strange printf output in C - c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char * reverse(char *string);
int main(int argc, char *argv[])
{
char array[10];
array[0] = 'a';
array[1] = 'b';
array[2] = 'c';
array[3] = 'd';
array[4] = 'e';
printf("1%s\n",array);
char *p = reverse(array);
printf("4%s\n",p);
printf("5%s\n",array);
}
char * reverse(char *string)
{
int size = strlen(string);
char reversed[size];
int i;
int j = 0;
for(i = size-1; i >= 0; i--)
{
reversed[j] = string[i];
j++;
}
printf("2%s\n",reversed);
string = reversed;
printf("3%s\n",string);
return reversed;
}
This code basically just initializes an array of values and passes it into a method that reverses these values.
I am not sure if this is the best way to execute the task, since I am new to pointers and arrays in C.
But the real question is this:
Can anyone figure out why in this line
printf("4%s\n",p);
if you remove the preceding '4', so it looks like so
printf("%s\n",p);
the line won't print at all?

You are returning a pointer to local variable(reversed) in the function reverse the question should actually be: Why did it work in the first place?.
This code string = reversed; will only copy the pointer, and again the local copy of the pointer so it has no effect outside the function.
To reverse a string you don't need additional memory - this can be done in-place.

Strings in C must end with the null character. You're using strlen on a non null-terminated string.

Furthermore, you just a very lucky person, because there is a serious problem with you code: you forget to add \0 symbol at the end of string.
UPD: the main problem is with code line char reversed[size];.
It's a regular local variable, it has automatic duration, which means that it springs into existence when the function is called and disappears when the function returns (see this link).
You need to change it to:
char *reversed = malloc((size+1)*sizeof(char));
UPD-2: another bug fixing will be:
1) add array[5] = '\0'; after all other array initializing lines
2) add reversed[j] = '\0'; after for...loop:
for(i = size-1; i >= 0; i--)
{
reversed[j] = string[i];
j++;
}
reversed[j] = '\0';
UPD-3: But in general it will much more correctly initialize your string in appropriate way:
char array[10] = "abcde";

Related

char-array (string) with arbitrary number of elements in c

I have problem with assigning value to string array in c. The code is part of a hangman game
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
int main()
{
srand(time(0));
int random = rand() % 5;
char *sWords[] = {"banana", "apple", "GOAT", "jordan", "zhiki"};
printf("%s\n", sWords[random]);
char *sTempWord = sWords[random];
char *sTempArr;
for (int i = 0; sTempWord[i] != '\0'; i++)
sTempArr[i] = '_';
for (int i = 0; strlen(sTempArr); i++)
printf("%c ", sTempArr[i]);
}
There are no errors, and when I run the program it just exits. The plan is to get random word from the list, create temporary array with the length of the randomly-selected word and assing all elements with value '_'.
Also, when I try to make array with constant value, (like char sTempArr[len] where len=strlen(sTempWord), it says: expression must have a constant value
When declaring an array, the compiler needs to know the length at compile time (e.g. the value can't be a variable).
You can either create an initial empty array with a known number of items (you will need to make sure it's big enough to fit any word from sWords, including null terminator):
char sTempArr[100];
or you can allocate dynamic memory at runtime with something like malloc():
#include <stdlib.h>
int len = strlen(sTempWord) + 1; // +1 for '\0'
char *sTempArr; = malloc(len);
// ...
free(sTempArr); // When you are done using the array
They are not the same.
Not initialized pointer.
char *sTempArr;
You do not null character terminate the string
for (int i = 0; sTempWord[i] != '\0'; i++)
sTempArr[i] = '_';
As the string is null character terminated you can't call strlen
for (int i = 0; strlen(sTempArr); i++)
printf("%c ", sTempArr[i]);
char sTempArr[strlen(sTempWord) + 1];
int i;
for (i = 0; sTempWord[i] != '\0'; i++)
sTempArr[i] = '_';
sTempArr[i] = 0;
for (i = 0; strlen(sTempArr); i++)
printf("%c ", sTempArr[i]);

create new converted string from "toupper()" in c

Trying to take a lower case string, and create a new string after making characters uppercase
#include <ctype.h>
#include <cs50.h>
#include <stdio.h>
#include <string.h>
int main (void)
{
string word = "science";
char new_word[] = {};
for (int i = 0, len = strlen(word); i < len; i++)
{
if (islower(word[i]))
{
new_word = new_word + toupper(word[i]);
}
}
}
I am getting "error: array type 'char[0]' is not assignable".
This isn't all, and I am sure with my full program there might be an easier way, but I built out everything else, and the only point that I am struggling with is looping through my string to get a new word that is uppercase.
Any assistance would be greatly appreciated!
char new_word[] = {};
Your new char array has length 0 and any access invokes undefined behaviour (UB) as you access it outside its bounds.
If your compiler supports VLAs:
string word = "science";
char new_word[strlen(word) + 1] = {0,};
if not:
string word = "science";
char *new_word = calloc(1, strlen(word) + 1);
and
new_word[i] = toupper((unsigned char)word[i]);
If you used calloc do not forget to free the allocated memory
Undefined behavior when word[i] < 0
Avoid that by accessing the string as unsigned char
As per C reference about toupper()
int toupper( int ch );
ch - character to be converted. If the value of ch is not representable as >unsigned char and does not equal EOF, the behavior is undefined.
This is not correct, compiler gives error , "error: assignment to expression with array type"
new_word = new_word + toupper(word[i]);
which is not allowed with an array type as LHS of assignment.
changed to
new_word[i] = toupper((unsigned char)word[i]);
#include <ctype.h>
#include <stdio.h>
#include <string.h>
int main (void)
{
char word[] = "science";
char new_word[sizeof word] = "";
int i;
for (i = 0; i < sizeof(word); i++)
{
if (islower(word[i]))
{
new_word[i] = toupper(word[i]);
}
else /* for Upper case latter, simply fill the array */
{
new_word[i] = word[i];
}
}
new_word[i] = '\0';
printf("%s", new_word);
}
OUTPUT:
SCIENCE
EDIT:
Just echo comment from solution given by M.M and comment from
David C. Rankin casting is not necessary for this example. read comment below from M.M and David C. Rankin
Removed unsigned char from islower() and toupper()
This is but one way of accomplishing the task. Make sure to come up with your way of doing.
#include <stdio.h>
#include <string.h>
#define MAX_BUFF 128
char *upperCase(char *c) {
//printf("%s, %d", c, strlen(c));
for(int i=0; i<strlen(c) && i<MAX_BUFF; i++) {
c[i] = c[i] - ' '; // convert char to uppercase
//printf(">> %c", c[i]);
}
return c;
}
int main (void)
{
char word[MAX_BUFF] = "science";
char new_word[MAX_BUFF];
printf("in>> %s \n", word);
strcpy(new_word, upperCase(&word[0]));
printf("out>> %s\n", new_word);
}
Output:
in>> science
out>> SCIENCE
Named arrays cannot be resized in C, you have to set the size correctly to start:
size_t len = strlen(word);
char new_word[len + 1]; // leaving room for null-terminator
Note that no initializer can be used for new_word when its size was determined by a function call (a lame rule but it is what it is); and you can take out the len loop variable since it is now defined earlier.
Then set each character in place:
new_word[i] = toupper(word[i]);
but be careful with the surrounding if statement: if that were false, then you need to set new_word[i] = word[i] instead.
(Pro tip, you can get rid of the if entirely, because toupper is defined to have no effect if the character was not lower case).
Lastly, there should be a null terminator at the end:
new_word[len] = 0;
NB. To be technically correct, the call to toupper should be: toupper((unsigned char)word[i]) -- check the documentation of toupper to understand more about this.

Reversing a string in C without the output being null

I am trying to reverse a string (character array) using the following code, but when I attempt to print the string, the value of null. This is a homework assignment, but I am trying to learn so any help would be appreciated.
void input_reverse_string(const char* inputStr, char* reverseStr)
{
int i = 0;
int length = 0;
for (; *(inputStr++) != '\0'; i++)
{
length++;
}
while (*inputStr)
{
*reverseStr = *inputStr;
inputStr++;
reverseStr++;
}
const char* chr_ptr = &inputStr[length - 1];
printf("I see a %s\n", *chr_ptr);
*reverseStr = '\0';
printf("%d", length);
/* return reverseStr; */
}
Several things are out of order:
That's a strange way of computing the length of a string. You are using an index variable that you don't need, and incrementing 3 things at the same time, it's unneeded to say the least.
After calculating the length, and incrementing the inputStr pointer up to its end, you don't reset the pointer, so it still points to the end of the string (actually, one after the end!).
Inside the while you are advancing both pointers (inputStr and reverseStr) in the same direction, which can't possibly be right if you want to reverse the string.
The correct way to do this would be:
Compute the length of the string. Either use strlen() or do it by hand, but you really only need to increment one variable to do this. You can avoid incrementing inputStr, just use a temporary pointer.
Start from inputStr + length and walk backwards. Either use a pointer and do -- or just index the string).
Here's a working example:
void reverse_string(const char* inputStr, char* reverseStr) {
unsigned len = 0;
int i;
while (inputStr[len])
len++;
for (i = len - 1; i >= 0; i--) {
reverseStr[len - i - 1] = inputStr[i];
}
reverseStr[len] = '\0';
}
int main(void) {
char a[6] = "hello";
char b[6];
reverse_string(a, b);
puts(b);
return 0;
}
Output:
olleh

Getting garbage after reversing string in c

I am trying to reverse a string. scanf is working well but when I use fixed string then it gives garbage value. So where is the fault ?
#include<stdio.h>
#include<string.h>
int main()
{
char s[50]="Hi I Love Programming";
char rev[strlen(s)];
int i,k;
k=strlen(s);
for(i=0; i<strlen(s); i++)
{
rev[k]=s[i];
k--;
}
printf("The reverse string is: %s\n", rev);
}
Your program has two issues:
1.
char rev[strlen(s)];
You forgot to add an element for the string-terminating null character '\0'.
Use:
char rev[strlen(s) + 1];
Furthermore you also forgot to append this character at the end of the reversed string.
Use:
size_t len = strlen(s);
rev[len] = '\0';
Note, my len is the k in your provided code. I use the identifier len because it is more obvious what the intention of that object is. You can use strlen(s) because the string has the same length, doesn´t matter if it is in proper or reversed direction.
2.
k=strlen(s);
for(i=0; i<strlen(s); i++)
{
rev[k]=s[i];
k--;
}
With rev[k] you accessing memory beyond the array rev, since index counting starts at 0, not 1. Thus, the behavior is undefined.
k needs to be strlen(s) - 1.
Three things to note:
The return value of strlen() is of type size_t, so an object of type size_t is appropriate to store the string length, not int.
It is more efficient to rather calculate the string length once, not at each condition test. Use a second object to store the string length and use this object in the condition of the for loop, like i < len2.
char s[50]="Hi I Love Programming"; can be simplified to char s[]="Hi I Love Programming"; - The compiler automatically detects the amount of elements needed to store the string + the terminating null character. This safes unnecessary memory space, but also ensures that the allocated space is sufficient to hold the string with the null character.
The code can also be simplified (Online example):
#include <stdio.h>
#include <string.h>
int main(void)
{
char s[] = "Hi I Love Programming";
size_t len = strlen(s);
char rev[len + 1];
size_t i,j;
for(i = 0, j = (len - 1); i < len; i++, j--)
{
rev[j] = s[i];
}
rev[len] = '\0';
printf("The reverse string is: %s\n", rev);
}
Output:
The reverse string is: pgnimmargorP evoL I iH
your program is hard to understand. Here you have something much simpler (if you want to reverse the string of course)
#include <stdio.h>
#include <string.h>
char *revstr(char *str)
{
char *start = str;
char *end;
if(str && *str)
{
end = str + strlen(str) - 1;
while(start < end)
{
char tmp = *end;
*end-- = *start;
*start++ = tmp;
}
}
return str;
}
int main()
{
char s[50]="Hi I Love Programming";
printf("%s", revstr(s));
}
https://godbolt.org/z/5KX3kP

exercise 9.7 Kochan. strange output

I am working to learn C using Kochan's Programming in C 4th edition. problem 9.7 the goal is to insert a string of characters into another array. I am supposed to write a function to accomplish this. I have two problems.
When I have the algorithm print the result as it goes through the if statements, it produces the desired output, however when I change it to an %s, I only get a partial output. My hunch is that a null character is being placed where i do not want it, but I simply cannot see it.
To see what was happening, I added a printf that would track the letter and the array space it was occupying. I was surprised to see that the first letter was not 0, but was blank, and the next letter was assigned the 0. Any insight into this would be appreciated.
The funtion of interest is "insertString".
#include <stdio.h>
#include <stdbool.h>
char x[] = {"the wrong son was shot that day"};
char text[] = {"per"};
int countString (char x[])
{
int counter, z;
for (counter = 0; x[counter] != '\0'; ++counter)
z = counter+1;
return z;
}
void insertString (char text[],char x[],int n) //source, text to input, where
{
int count, clock, i = countString(text), q = countString(x);
int counter = 0;
char y[i + q];
for(count = 0; x[count] != '\0'; ++count){
if (count < n){
y[count] = x[count];
printf("%c %i", y[count], count); //The integer call is just to put a number next to the
//letter. This is where my second issue is shown.
}
else if (counter <= i){
y[count] = text[counter];
++counter;
printf("%c", y[count]);
}
else{
y[count]= x[count - counter];
printf("%c", y[count]);
}
}
printf("\n\n");
y[count-counter] = '\0';
printf("%s", y);
}
int main (void)
{
void insertString(char text[], char x[], int i);
int countString(char x[]);
int i;
insertString(text, x, 10);
return 0;
}
10 out of 10 times I post here it is because im doing something dumb, so I use SO as an absolute last resort if i am getting into the territory of just randomly trying stuff with no methodology. Thanks for your patience in advance.
Your condition is wrong in the for. It should be x[count - counter] != '\0'
In the second condition use just < to avoid overindexing. (else if (counter < i))
You put the terminating NULL char at wrong place. You should do this: y[count] = '\0'
printf inside a string routine like this is fine for debugging, but it's a poor way to write a general-purpose function because it makes it impossible to use its output for further programmatic manipulation. It can also make it difficult to reason about how the state of the function interacts in unpredictable ways with the state of the printed data.
I assume you haven't learned about dynamic memory allocation which is a prerequisite to returning strings from functions. You can inline the function logic into main or printf only at the end of the function in the meantime.
Adding to this point, a void function would need to reallocate space in the string to insert into and would be in-place. This seems likely less generally useful than allocating a new string to hold the result.
Using global variables like char x[] when there's no need is poor practice. It's better to put those strings scoped to main. Since your function can access these variables in addition to its parameters, confusion can ensue when scope and encapsulation is breached.
Use consistent formatting and avoid variable names like q that mean virtually nothing. Instead of adding comments to explain poor var names:
void insertString (char text[],char x[],int n) //source, text to input, where
You can simply name the variables exactly what they represent:
void insertString(char *dest, char *source, int add_index)
Also, now that you've mastered countString, you can abstract this by calling the builtin strlen.
Be sure to allocate enough space in buffers: char y[i + q]; should be y[i+q+1] to allow room for the null terminator '\0'.
As for the logic, I think it's easier to break into three loops without conditions instead of one loop with conditions. This makes it easier to break the problem down into the three constituent steps:
Add everything up until add_index from the dest string to the result.
Add everything in the source string to the result.
Add everything after add_index from the dest string to the result.
Using this approach, all that's left is figuring out how to map the indexes appropriately. Here it is in code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *insert_string(char *dest, char *source, int add_index) {
int source_len = strlen(source);
int dest_len = strlen(dest);
int result_size = source_len + dest_len + 1;
char *result = malloc(result_size);
for (int i = 0; i < add_index; i++) {
result[i] = dest[i];
}
for (int i = 0; i < source_len; i++) {
result[i+add_index] = source[i];
}
for (int i = add_index; i < dest_len; i++) {
result[i+add_index] = dest[i];
}
result[result_size-1] = '\0';
return result;
}
int main(void) {
char *result = insert_string("hello world", "cruel ", 6);
printf("%s\n", result);
free(result);
return 0;
}
Although this is likely for instructional purposes, these operations can be abstracted further using builtin string functions like strncpy and sprintf.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *insert_string(char *dest, char *source, int add_index) {
int result_size = strlen(dest) + strlen(source) + 1;
char *result = malloc(result_size);
char pre[add_index+1];
pre[add_index] = '\0';
strncpy(pre, dest, add_index);
sprintf(result, "%s%s%s", pre, source, dest + add_index);
return result;
}
int main(void) {
char *result = insert_string("hello world", "cruel ", 6);
printf("%s\n", result);
free(result);
return 0;
}
Doing this in-place is more straightforward. Since the result already has the prefix, you can copy the destination postfix to create a source-sized gap in the middle and then overwrite the gap using the source string. It's up to the caller to make sure that the destination buffer is large enough to hold the insertion.
#include <stdio.h>
#include <string.h>
void insert_string(char *dest, char *source, int add_index) {
int source_len = strlen(source);
int dest_len = strlen(dest);
for (int i = add_index; i < dest_len; i++) {
dest[i+add_index] = dest[i];
}
for (int i = 0; i < source_len; i++) {
dest[i+add_index] = source[i];
}
}
int main(void) {
// allocate extra space in the string to hold the insertion
char greeting[32] = "hello world";
insert_string(greeting, "cruel ", 6);
printf("%s\n", greeting);
return 0;
}
A note of caution: none of these functions handle errors at all, so they're unsafe. Correct functions should check that the add_index falls within the bounds of the dest string. This is an exercise for the reader.
The original exercise is here:
Your function is not doing it. You need to insert the string into another string not to create a new one with both mixed. You can do it this way of course and then copy it into the original one - but it is the most uneficient way to archive it (memory & timewise).
Use the correct types.
size_t mystrlen(const char *str)
{
const char *end = str;
while(*end++);
return end - str - 1;
}
char *strinsert(char *dest, size_t pos, const char *istr)
{
char *temp = dest, *work;
size_t ilen = mystrlen(istr);
size_t nmove;
while(*temp) temp++;
nmove = temp - dest - pos + 1;
work = temp;
temp += ilen;
while(nmove--) *temp-- = *work--;
work = dest + pos;
while(*istr) *work++ = *istr++;
return dest;
}
int main()
{
char dest[128] = "0123456789012345678901234567890123456789";
printf("%s", strinsert(dest, 7, "ABCD"));
}
https://godbolt.org/z/KMnLU2

Resources