My homework problem is to make a program putting 3 strings together using strcpy, strcat, sprintf at least once each.
I'm wondering if I can use all those three without any garbage code. I've tried using strchr to use sprintf for putting strings together, but the pointer location changed so couldn't print out the whole thing.
char str1[MAX];
char str2[MAX];
char str3[MAX];
char str4[MAX];
gets(str1);
gets(str2);
gets(str3);
strcat(str1, str2);
strchr(str1, '\0');
sprintf(str1, "%s", str3);
strcpy(str4, str1);
puts(str4);
I also want to know if there is any difference in their use between strcpy and sprintf in this case.
Lets say str1 = "ab", str2 = "cd", str3 = "ef"
strcat(str1, str2);
This will concatenate str2 onto str1,
now
str1 = "abcd"
strchr(str1, '\0'); // this will not do anything, it will just return pointer of '\0' in str1, which is the last chatracter.
sprintf(str1, "%s", str3);
this will print "ef" into str1, old content will be lost,
I believe you wanted to do
sprintf(<pointer returned from strchr>, "%s", str3);
strcpy(str4, str1);
This will just copy str1 to str4.
puts(str4);
This will print the string str4
The problem with your code is where you are doing strchr and not collecting the return value, so that you can concatenate there.
In this case strcpy and sprintf are similar, but sprintf gives you lot of formatting options, see documentation.
http://www.cplusplus.com/reference/cstdio/sprintf/
Also, your MAX macro should be large enough to hold strings.
This doesn't do anything: strchr(str1,'\0'). Read the documentation of strchar carefully. But you don't need strchr here anyway, you proably just want this:
...
gets(str1);
gets(str2);
gets(str3);
strcpy(str4, str1); // copy str1 into str4
strcat(str4, str2); // append str2 to str4
strcat(str4, str3); // append str3 to str4
puts(str4); // print str4
As you can see, you don't need sprintf either.
But you can do the same thing using only sprintf
...
gets(str1);
gets(str2);
gets(str3);
sprintf(str4, "%s%s%s", str1, str2, str3);
puts(str4);
but then you don't need strcpy nor strcat.
Using all strcpy, strcat and sprintf is a somewhat pointless requirement, but now you should be able to do it.
Related
This question already has answers here:
What is the value of an uninitialized string in c? [duplicate]
(6 answers)
Closed 1 year ago.
I'm trying to concatenate multiple strings to create a longer phrase but I get weird, seemingly random, characters in front of the phrase when I try to print it. Here is the code:
char* str2 = argv[2];
int len2 = strlen(str2);
char* str3 = argv[3];
int len3 = strlen(str3);
printf("child PID(%d) receives Y = '%s' and Z= '%s' from the pipe\n",getpid(), str2, str3 );
//get the length of arguments 2 and 3 and create an array that is 1 larger than that (for the space between the two phrases)
//then concatenate them
int catLen = len2+len3;
char conc[catLen + 1];
strcat(conc, str2);
strcat(conc," ");
strcat(conc, str3);
printf("child PID(%d) concatenates Y and Z to generate Y' = '%s'\n",getpid(),conc);
int len1;
//get the length of the first command-line argument in the pipe
read(port[0],&len1,sizeof(len1));
//get the first command-line argument from the pipe
char str1[len1];
read(port[0], &str1,len1);
printf("child PID(%d) reads X from the pipe = '%s'\n",getpid(),str1);
//problems start when concatenating strings here
int totalLen = len1+catLen+1;
char phrase[totalLen];
strcat(phrase, str1);
printf("%s\n",phrase);
strcat(phrase," ");
printf("%s\n",phrase);
strcat(phrase,conc);
printf("child PID(%d) concatenates X and Y' to generate Z' = '%s'\n",getpid(),phrase);
I only encounter this issue when I try and concatenate the second set of strings, and I don't understand why. What is different between how I did it earlier and at the bottom the program?
First of all,
as Ptit Xav points out, you need one additional byte of space for conc. You need len1 bytes for the first string, plus 1 for the space, plus len2 for the second string, and then one more for the terminating null character. So if catLen = len1 + len2, then you should declare char cond[catLen + 2]; (or change the calculation of catLen in some equivalent way).
Next, when you declare a local array like char conc[catLen + 2]; without initializing it, it contains garbage. If you then attempt to strcat onto it, you concatenate onto garbage. If the garbage happens not to contain any null bytes, then strcat will overrun the array searching for a null byte, causing undefined behavior (which is very bad).
So either make your first use a strcpy instead of strcat:
char conc[catLen + 2];
strcpy(conc, str2); // note strcpy here
strcat(conc," ");
strcat(conc, str3);
Or else set the first character of your array to be a null character before starting, so that it becomes an empty string:
char conc[catLen + 2];
conc[0] = '\0'; // conc now contains an empty string
strcat(conc, str2);
strcat(conc," ");
strcat(conc, str3);
You can also initialize the array:
char conc[catLen + 2] = "";
strcat(conc, str2);
strcat(conc," ");
strcat(conc, str3);
However this will cause the program to fill the entire array conc with null bytes, where you really only needed one, so it is inefficient.
This post might be marked as a duplicate, but I did search online for this specific case and I couldn't find any examples similar to this. The following is a simplified version of my code.
I have the following lines of data stored with a text file named test.txt:
12345|This is a sentence|More words here
24792|This is another sentence|More words here again
The text in the test.txt file will always follow the format of <int>|<string>|<string>
I now want to store each of the sections separated by the delimiter | in a variable.
The following is my attempt:
uint32_t num;
char* str1, str2;
// the data variable is a char pointer to a single line retrieved from test.txt
sscanf(data, "%d|%s|%s", &num, str1, str2);
This code above would retrieve the correct value for num but would insert the first word from section two into str1, leaving the variable str2 as null. To my understanding, this was the case because the sscanf() function stops when it hits a space.
Is there an efficient way of storing each section into a variable?
As you noted, %s uses whitespace as the delimiter. To use | as the delimiter, use %[^|]. This matches any sequence of characters not including |.
And since num is unsigned, you should use %u, not %d.
sscanf(data, "%u|%[^|]|%[^|]", &num, str1, str2);
Don't forget to allocate memory for str1 and str2 to point to; scanf() won't do that automatically.
Your variable declarations are also wrong. It needs to be:
char *str1, *str2;
Your declaration is equivalent to:
char *str1;
char str2;
I`ve been trying to this for quite a while now and after some research I had no success, so my last resort was asking a question. My input looks like this:
1.0.0.0/255.0.0.0/127.0.0.1/1112
1.2.0.0/255.255.0.0/2.4.6.9/1112
1.2.3.0/255.255.255.0/1.2.3.1/111
I need to extract 4 strings from each line, so for exemple the first line would give me
s1 = 1.0.0.0
s2 = 255.0.0.0
s3 = 127.0.0.1
s4 = 1112
Here is what I have tried:
scanf("%s/%s/%s/%s", str1, str2, str3, str4); // This doesn't consume the "/"
scanf("%[^/]s%[^/]s%[^/]s%[^/]s", str1, str2, str3, str4); // This only gets the first string
scanf(""%[^\n]s%*c%s%*c%s%*c%s", str1, str2, str3, str4); // Hera %*c was supposed to consume the "/" and do not store it, it doen't happen tho
How can I get the 4 strings from each input line using a single scanf inside a while (!feof(fileIn)) ? Thank you.
There are a few issues with the posted code. The scanset directive is %[]; there is no s in this. The format strings using %[^/]s are attempting to match a literal s in the input. But this will always fail because %[^/] matches any character except for /. When a / is encountered, the match fails and the / character is left in the input stream. It is this character which must be consumed before continuing on to the next input field.
Also, note that while(!feof(file)){} is always wrong. Instead, try fetching input by lines using fgets(), and parsing with sscanf(). The fgets() function returns a null pointer when end-of-file is reached.
Further, you should always specify a maximum width when reading strings with scanf() family functions to avoid buffer overflow.
Here is an example program:
#include <stdio.h>
int main(void)
{
char input[4096];
char str1[100];
char str2[100];
char str3[100];
char str4[100];
while (fgets(input, sizeof input, stdin)) {
sscanf(input, " %99[^/]/ %99[^/]/ %99[^/]/ %99[^/]",
str1, str2, str3, str4);
puts(str1);
puts(str2);
puts(str3);
puts(str4);
}
return 0;
}
Sample interaction using sample input from the question:
λ> ./a.out < readstring_test.txt
1.0.0.0
255.0.0.0
127.0.0.1
1112
1.2.0.0
255.255.0.0
2.4.6.9
1112
1.2.3.0
255.255.255.0
1.2.3.1
111
You already got quite close: you missed to consume the delimiter in your second approach:
scanf("%[^/]/%[^/]/%[^/]/%[^/]", str1, str2, str3, str4);
should do the job.
I have string having multiple words separated with commas like
char str[]="K&R,c89,c99,c11";
I am trying to read the first 2 words into a separate character arrays using sscanf().
sscanf(str, "%[^,] s%[^,]s", str1, str2);
I intended sscanf() to scan through str till reaching a ,, store it to str1, continue scanning till another , and store into str2.
But value is being stored only into str1 while str2 seem to be having garbage.
I tried removing the space between the %[^,]ss if that was of any significance but it made no difference on the output.
What am I doing wrong? Or is this not possible for multiple words?
I've heard of doing something like this with strtok() but I was wondering if sscanf() could be used for this.
Duh.. It took me a while to see it. Get rid of the s in your format string. The character class [...] takes the place of s and by putting s in there, you are forcing sscanf to look for a literal s in str, e.g.
#include <stdio.h>
#define MAX 8
int main (void) {
char str[]="K&R,c89,c99,c11";
char str1[MAX] = "";
char str2[MAX] = "";
if (sscanf(str, "%[^,],%[^,]", str1, str2) == 2)
printf ("str1 : %s\nstr2 : %s\n", str1, str2);
return 0;
}
Example Use/Output
$ ./bin/sscanfcomma
str1 : K&R
str2 : c89
Also, consider protecting your arrays from overflow with, e.g.
if (sscanf(str, "%7[^,],%7[^,]", str1, str2) == 2)
I am confused with one tiny program.
#include <stdio.h>
#define LEN 10
int main()
{
char str1[LEN] = "\0";
char str2[LEN] = "\0";
scanf("%s", str1);
scanf("%s", str2);
printf("%s\n", str1);
printf("%s\n", str2);
return 0;
}
If my input are:
mangobatao
mangobatao123456
Why should the output be:
123456
mangobatao123456
And not:
mangobatao
mangobatao123456
How has the char array has been allocated in the memory?
Well, a 10 character char array won't fit "mangobatao", since it has 10 characters - there's no room for the null terminator. That means you've caused undefined behaviour, so anything could happen.
In this case, it looks like your compiler has laid out str2 before str1 in memory, so when you call scanf to fill str2, the longer string overwrites the beginning of str1. That's why you see the end of what you think should be in str2 when trying to print str1. Your example will work fine if you use a length of 100.
I think your compiler has allocated space for str2[10] just 10 characters before the str1 pointer.
Now, when you scanf a string of length 16 at str2, the string terminator '\0' is appended at str2 + 17th position, which is infact str1 + 7.
Now when you call printf at str1, the characters read are actually str2 + 11, str2 + 12,..., str2 + 16 until the null terminator is encountered at str2 + 17 (or str1 + 7).
The printf at str2 must be obvious.