it seems like such a silly thing to ask but i seriously don't know why this is happening. Could be that it's almost 5am and i'm still doing this but..
It should print -CA but why when i compile it, it is printing
-
CA?
instead of -CA, there isn't a '\n' anywhere in sight.
Can you guys think of anything logical that would explain it?
int main(int argc, char* argv[]){
int check = 0;
char *thing = (char*)malloc(2 * sizeof(char));
strcpy(char, "CA");
some code..
do{
more code...
if(condition== 1) {
more code....
if(check == 0) {
printf("-");
check++;
}
if (some conditon != NULL){
printf("%s\n",thing);
}while(condition)
return 0;
}
You didn't allocate enough space for your string. Every string has a null terminator, so a 2-character string needs 3 bytes in the array. Your strcpy() is writing outside the bounds of the thing array when it copies the null byte, which results in undefined behavior.
Use
char *thing = malloc(3);
You can also use strdup(), which makes a copy of a string in dynamic memory, automatically allocating enough space based on the length of the original string.
char *thing = strdup("CA");
printf prints a null terminated string to the stdout. if the sting is not null terminated the printf will go on printing garbage to the stdout till a null terminator is met
so you should all one to your character array
char thing[3] = {'C','A',0};
now printf will print
-
CA
Related
I am trying to reverse a string in C with pointers but the output is really weird. The logic seems good but I am not sure why it gets outputted like this. Here is the code:
#include <stdio.h>
#include <string.h>
int main()
{
char str[20], reverse_str[20], *pointer;
int i = 0;
printf("%s", "Enter any string: ");
scanf("%s", str);
pointer = str;
int string_length = strlen(pointer);
//int count = 0;
for (int i = string_length; i > 0; i--){
reverse_str[i -1] = *pointer;
pointer++;
}
printf("%d\n", string_length);
printf("Original string = %s\n", str);
printf("Reversed string = %s\n", reverse_str);
}
The output looks like this:
Enter any string: Hello
Original string = Hello
Reversed string = olleH╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠Hello
This is when the role of null terminator comes in which is often ignored as a silly bit of information by beginners.
In C, every string is terminated by a null character because there needs to be some way to know when a particular string ends starting from its initial location in memory. If you properly initialize the string or put in \0 appropriately then the string can be displayed as is. Otherwise every character in memory starting from the zeroth index of the string will be displayed until it encounters a null character. This is how a printf("%s", str) works, in simple words.
You get that weird output because of this reason. This explains it much better.
Solution:
Add reverse_str[string_length] = '\0'; after you reverse your string using that for loop, so that your resultant string is properly null terminated.
Bonus:
And the reason why you got a considerably sane output is that you were lucky since the compiler allocated str and reverse_str close to each other in a direction such that even if you miss the null terminator on reverse_str you hit the null terminator of str.
To print a string, the string needs a NUL-terminator \0 but reverse_str doesn´t have one.
You need to set a \0 at the end of revers_str, like:
reverse_str[string_length] = '\0';
to make it print the right output.
i trying to create a function that return an array of zeros us a char array
and print this array in a file text but when i return a string an addition char was returned
this the text file string the program wrote
this my fuction :
char *zeros_maker (int kj,int kj1)
{
char *zeros;
zeros = (char *) malloc(sizeof(char)*(kj-kj1));
int i;
for(i =0;i<kj-kj1;i++)
zeros[i]='0';
printf("%s\n",zeros);
return zeros;
}
the instruction i used when i printed in the file
fprintf(pFile,"%c%s%c &",34,zeros_maker(added_zeros,0),34);
Thanks in advance
'0' in C is the value of the encoding used for the digit zero. This is not allowed to have the value 0 by the C standard.
You need to add a NUL-terminator '\0' to the end of the char array, in order for the printf function to work correctly.
Else you run the risk of it running past the end of the char array, with undefined results.
Finally, don't forget to free the allocated memory at some point in your program.
Read about how string in C are meant to be terminated.
Each string terminates with the null char '\0' (the NULL symbol ASCII value 0, not to be confused with the char '0' that has ASCII value 48). It identifies the end of the string.
zeros[kj-kj1]='\0';
Plus check always if you are accessing an element out of bound. In this case it happens if kj1> kj
Instead of for loop, you may get hand of memset.
char* zeros_maker(int kj,int kj1)
{
int len=kj-kj1;
char *zeros=malloc(sizeof(char)*(len));
memset(zeros,'0',len-1);
zeros[len-1]=0;
printf("%s\n",zeros);
//fflush(stdout);
return zeros;
}
Or if you are not fan of C-style string, and it's going to be ASCII only, following could be used too. Just be careful what your are doing this way.
char* zeros_maker_pascal_form(int kj,int kj1)
{
int len=kj-kj1;
char *zeros=malloc(sizeof(char)*(len));
memset(zeros,'0',len);
for(int a=0;a<len;a++){
printf("%c",zeros[a]);
}
printf("\n");
//fflush(stdout);
return zeros;
}
Your code has a few basic issues, the main one is that it fails to terminate the string (and include space for the terminator).
Here's a fixed and cleaned-up version:
char * zeros_maker(size_t length)
{
char *s = malloc(length + 1);
if(s != NULL)
{
memset(s, '0', length);
s[length - 1] = '\0';
}
return s;
}
This has the following improvements over your code:
It simplifies the interface, just taking the number of zeroes that should be returned (the length of the returned string). Do the subtraction at the call site, where those two values make sense.
No cast of the return value from malloc(), and no scaling by sizeof (char) since I consider that pointless.
Check for NULL being returned by malloc() before using the memory.
Use memset() to set a range of bytes to a single value, that's a standard C function and much easier to know and verify than a custom loop.
Terminate the string, of course.
Call it like so:
char *zs = zeros_maker(kj - kj1);
puts(s);
free(s);
Remember to free() the string once you're done with it.
I'm coding a program that takes some files as parameters and prints all lines reversed. The problem is that I get unexpected results:
If I apply it to a file containing the following lines
one
two
three
four
I get the expected result, but if the file contains
september
november
december
It returns
rebmetpes
rebmevons
rebmeceds
And I don't understand why it adds a "s" at the end
Here is my code
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void reverse(char *word);
int main(int argc, char *argv[], char*envp[]) {
/* No arguments */
if (argc == 1) {
return (0);
}
FILE *fp;
int i;
for (i = 1; i < argc; i++) {
fp = fopen(argv[i],"r"); // read mode
if( fp == NULL )
{
fprintf(stderr, "Error, no file");
}
else
{
char line [2048];
/*read line and reverse it. the function reverse it prints it*/
while ( fgets(line, sizeof line, fp) != NULL )
reverse(line);
}
fclose(fp);
}
return (0);
}
void reverse(char *word)
{
char *aux;
aux = word;
/* Store the length of the word passed as parameter */
int longitud;
longitud = (int) strlen(aux);
/* Allocate memory enough ??? */
char *res = malloc( longitud * sizeof(char) );
int i;
/in this loop i copy the string reversed into a new one
for (i = 0; i < longitud-1; i++)
{
res[i] = word[longitud - 2 - i];
}
fprintf(stdout, "%s\n", res);
free(res);
}
(NOTE: some code has been deleted for clarity but it should compile)
You forget to terminate your string with \0 character. In reversing the string \0 becomes your first character of reversed string. First allocate memory for one more character than you allocated
char *res = malloc( longitud * sizeof(char) + 1);
And the try this
for (i = 0; i < longitud-1; i++)
{
res[i] = word[longitud - 2 - i];
}
res[i] = '\0'; // Terminating string with '\0'
I think I know the problem, and it's a bit of a weird issue.
Strings in C are zero terminated. This means that the string "Hi!" in memory is actually represented as 'H','i','!','\0'. The way strlen etc then know the length of the string is by counting the number of characters, starting from the first character, before the zero terminator. Similarly, when printing a string, fprintf will print all the characters until it hits the zero terminator.
The problem is, your reverse function never bothers to set the zero terminator at the end, which it needs to since you're copying characters into the buffer character by character. This means it runs off the end of your allocated res buffer, and into undefined memory, which just happened to be zero when you hit it (malloc makes no promises of the contents of the buffer you allocate, just that it's big enough). You should get different behaviour on Windows, since I believe that in debug mode, malloc initialises all buffers to 0xcccccccc.
So, what's happening is you copy september, reversed, into res. This works as you see, because it just so happens that there's a zero at the end.
You then free res, then malloc it again. Again, by chance (and because of some smartness in malloc) you get the same buffer back, which already contains "rebmetpes". You then put "november" in, reversed, which is slightly shorter, hence your buffer now contains "rebmevons".
So, the fix? Allocate another character too, this will hold your zero terminator (char *res = malloc( longitud * sizeof(char) + 1);). After you reverse the string, set the zero terminator at the end of the string (res[longitud] = '\0';).
there are two errors there, the first one is that you need one char more allocated (all chars for the string + 1 for the terminator)
char *res = malloc( (longitud+1) * sizeof(char) );
The second one is that you have to terminate the string:
res[longitud]='\0';
You can terminate the string before entering in the loop because you know already the size of the destination string.
Note that using calloc instead of malloc you will not need to terminate the string as the memory gets alreay zero-initialised
Thanks, it solved my problem. I read something about the "\0" in strings but wasn't very clear, which is now after reading all the answers (all are pretty good). Thank you all for the help.
reverser() reverses a cstring (not in place). 99% of the time it works but some input corrupts it for example it appears if aStr2[] is assigned a string made up of the same character it will have an error.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* reverser(const char *str);
int main()
{
char aStr[] = "aaa";
char aStr2[] = "cccccc";
printf("%s %s", aStr, aStr2);
char* tmp = reverser(aStr2);//tmp now has garbage
printf("\n%s", tmp);
printf(" %s", aStr2);
return 0;
}
char* reverser(const char *str)
{
char* revStr = (char*)malloc(strlen(str));
int i;
for(i = strlen(str)-1; i >= 0; i--)
{
revStr[strlen(str)-1-i] = str[i];
}
return revStr;
}
Gives
aaa cccccc
cccccc9 cccccc
Process returned 0 (0x0) execution time : 0.068 s
Press any key to continue
Notice the 9 that shouldn't be there.
Change this malloc to strlen(str) + 1 , plus 1 for '\0'
char* revStr = (char*)malloc(strlen(str) + 1);
and after the for loop
revStr[strlen(str)+1] = '\0';
Your problem is that you don't put the string terminator in your reversed string. All strings in C are actually one extra character that isn't reported by strlen, and that is the character '\0' (or plain and simple, a zero). This tells all C functions when the string ends.
Therefore you need to allocate space for this extra terminator character in your malloc call, and add it after the last character in the string.
There are also a couple of other problems with your code, the first is that you should not cast the return of malloc (or any other function returning void *). Another that you have a memory leak in that you do not free the memory you allocate. This last point doesn't matter in a small program like the one you have here, but will be an issue in larger and longer running programs.
You haven't null-terminated your reversed string. You need to set the final index of revStr[] to 0.
I am processing an input string, which consists of a process name, followed by an arbitrary amount of arguments.
I need the process name , along with all of the arguments, in one string.
I thought I could use strcat in a loop, so that it cycles through all of the args and each time appends the arg to the string, but I am having problems with getting a string that in empty to begin the loop.
Can anyone help me out with some basic code?
Thanks.
EDIT:
I'm posting my code for clarity. Mike's post is closest to what I have now:
char * temp;
strcpy(temp,"");
for (i = 4; i < argc-1; i++) // last arg is null, so we need argc-1
{
strcat(temp,argv[i]);
strcat(temp," ");
}
ignore the 4 in my for loop for the moment (magic number, i know.)
I am getting a segfault with this code. Is it because of my string assignment? I assume that is the case and hence I asked the question of how i could combine the strings.
Let's say your input strings are in an array of char pointers, suggestively called argv, of length argc.
We first need to determine how much space is needed for the output:
int length = 0;
for (int i = 0; i < argc; ++i)
length += strlen(argv[i]);
Then we allocate it, adding an extra char for the '\0' terminator:
char *output = (char*)malloc(length + 1);
Finally, the concatenation:
char *dest = output;
for (int i = 0; i < argc; ++i) {
char *src = argv[i];
while (*src)
*dest++ = *src++;
}
*dest = '\0';
Note that I don't use strcat here. Reason is that this sets us up for a Schlemiel the Painter's algorithm: for each iteration, the entire output string would be scanned to find its end, resulting in quadratic running time.
Don't forget to free the output string when you're done:
free(output);
I'm a bit tired so I may be overlooking something here. A better solution, using standard library functions, is welcome. It would be convenient if strcat returned a pointer to the terminator byte in dest, but alas.
You want an empty C string? Is this what you are looking for: char p[] = "";?
UPDATE
After you posted some code it is clear that you have forgotten to allocate the buffer temp. Simply run around the arguments first, counting up the length required (using strlen), and then allocate temp. Don't forget space for the zero terminator!
You could provide the "arbitrary amount of arguments" as one argument, ie an array/list, then do this pseudocode:
str = "";
i = 0;
while i < length of input
{
str = strcat ( str , input[i]);
i++;
}
#include<stdio.h>
#include<stdarg.h>
int main(int argc, char** argv) {
// the main parameters are the same situation you described
// calling this program with main.exe asdf 123 fdsa, the program prints out: asdf123fdsa
int lengths[argc];
int sum =0;
int i;
for(i=1; i<argc; i++) { // starting with 1 because first arg is program-path
int len = strlen(argv[i]);
lengths[i] = len;
sum+=len;
}
char* all = malloc(sum+1);
char* writer = all;
for(i=1; i<argc; i++) {
memcpy(writer, argv[i], lengths[i]);
writer+=lengths[i];
}
*writer = '\0';
printf("%s\n", all);
system("pause");
return 0;
}
A string in C is represented by an array of characters that is terminated by an "null" character, '\0' which has the value 0. This lets all string functions know where the end of a string is. Here's an exploration of different ways to declare an empty string, and what they mean.
The usual way of getting an empty string would be
char* emptyString = "";
However, emptyString now points to a string literal, which cannot be modified. If you then want to concatenate to an empty string in your loop, you have to declare it as an array when you initialize.
char buffer[] = "";
This gives you an array of size one. I.e. buffer[0] is 0. But you want an array to concatenate to- it has to be large enough to accomodate the strings. So if you have a string buffer of certain size, you can initialize it to be empty like so:
char buffer[256] = "";
The string at buffer is now "an empty string". What it contains, is buffer[0] is 0 and the rest of the entries of the buffer might be garbage, but those will be filled once you concatenate your other strings.
Unfortunately, the problem with C, is you can never have an "infinite" string, where you are safe to keep concatenating to, you have to know it's definite size from the start. If your array of arguments are also strings, you can find their length using strlen. This gives you the length of a string, without the null character. Once you know the lengths of all your sub-strings, you will now know how long your final buffer will be.
int totalSize; // assume this holds the size of your final concatenated string
// Allocate enough memory for the string. the +1 is for the null terminator
char* buffer = malloc(sizeof(char) * (totalSize + 1));
buffer[0] = 0; // The string is now seen as empty.
After this, you are free to concatenate your strings using strcat.