Reputation: 11483
I'm attempting to convert command-line arguments into a single char*
or "c-string" reference, however it seems my code is breaking. There aren't any compiler warnings, so I'm a bit stuck at this point
#include <stdio.h>
#include <string.h>
int main(int argc, char** argv) {
if (argc < 2) {
printf("usage: program <arguments>");
return 0;
}
char* string = "";
for (int i = 1; i < argc; i++) {
strcat(string, argv[i]);
}
printf("%s", string);
printf("\n");
return 0;
}
Compiling with:
gcc program.c -Wall -std=c99 -o prog
Doesn't seem to throw any warnings, so where could I be going wrong?
Edit:
Updates code to this point:
#include <stdio.h>
#include <string.h>
int main(int argc, char** argv) {
if (argc == 0) {
printf("usage: program <arguments>");
return 1;
}
int tot = 0;
for (int i = 1; i < argc; i++) {
tot += strlen(argv[i]);
}
char string[tot + argc]; // total word length
strcat(string, "\0");
for (int i = 1; i < argc; i++) {
strcat(string, argv[i]);
strcat(string, " ");
}
strcat(string, "\0");
printf("%s", string);
printf("\n");
return 0;
}
However a new problem arises, in that it appears to prepend pseudo-random garbage characters to the string. I added this to the catenation loop to look at the output:
for (int w = 0; w < sizeof(argv[i]); w++) {
printf("\t%s%c\n", "char value: ", argv[i][w]);
}
And this was the output:
./prog one two three
char value: o
char value: n
char value: e
char value:
char value: t
char value: w
char value: o
char value:
char value: t
char value: h
char value: r
char value: e
Tëñ¿one two three
So my guess is that the issue lays within the argument not having a proceeding \0
value, but not 100% certain of how to proceed. Would creating a new array of char
to append to, then catenating that be appropriate?
Upvotes: 1
Views: 2698
Reputation: 1997
You're attempting to write into a literal string. Two problems: 1) literal strings aren't generally placed in writable memory. 2) the string (character array) is of size zero; there's no room to write in to it.
The quick answer is to allocate a buffer on the heap:
char* string = (char*)malloc(256);
or on the stack:
char string[256];
Ideally you'd avoid picking a constant size like 256. One approach would be to loop over argv twice - once to measure how much space you'll need, and then again to perform the copies.
Upvotes: 0
Reputation: 510
You need to count the total space first:
for (int i = 1; i < argc; i++) {
total += strlen(argv[i]);
}
Then allocate space for final string:
string = calloc(1, total+1);
+1 is for null terminator ('\0').
Then you can strcat to string, and remeber to free it when you don't need it anymore.
Here is the full working code (without error checking):
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char** argv) {
int total = 0;
int i;
if (argc < 2) {
printf("usage: program <arguments>");
return 0;
}
char *string;
for (i = 1; i < argc; i++) {
total += strlen(argv[i]);
}
string = calloc(1, total+1);
for (i = 1; i < argc; i++) {
strcat(string, argv[i]);
}
printf("%s", string);
printf("\n");
free(string);
return 0;
}
Upvotes: 1
Reputation: 977
the way you declare string
make the memory that string
point to can't be modified.
Instead, you can declare string
as char array if you know max size needed. And you'd beter do length checking to make sure it's not overrun when you do strcat
char string[1024]; // put the size you needed
Or you can dynamically allocate space. As suggested by @moeCake.
Upvotes: 0