I/O - Manipulation of C Strings - c

I'd like to iterate through a string (entered by the user), returning the inputted string with an added space after each character (i.e. "Hello" --> "H e l l o ".
If I preset the value for str (i.e. char str[] = "Hello";) then the desired result is printed ("H e l l o "), but not so with user input (i.e. If the user inputs "Hello" the output is "H"). How does one successfully extract and manipulate a C string based on user input?
#include <stdio.h>
#include <string.h>
int main()
{
char str[] = "";
printf("\nEnter a string: ");
scanf("%s", &str);
printf("\nYou typed: %s \n", str);
int i = 0;
char newstr[150] = "";
for (i = 0; i < strlen(str); i++)
{
newstr[2*i] = str[i];
newstr[2*i+1] = ' ';
}
newstr[2 * strlen(str)] = '\0';
printf("\nExpanded String: ");
printf("%s", newstr);
return 0;
}

Here:
char str[] = "";
the size of str is inferred from the initializer, which is in this case one byte large. Thus str cannot hold a string larger than one byte, and since the zero-terminator is one byte large, there is no more space for a payload. A fix is to specify a size:
char str[1024] = "";
Now str has enough space for a kilobyte of data, or 1023 characters in addition to the terminator. The size is deliberately chosen to be much larger than the input you expect.
In addition to this, it would be a good idea to prevent scanf from writing past the end of the buffer by including the size in the format string. That is
scanf("%1023s", str); // now scanf will not read more than 1023 bytes plus sentinel.
...and in turn, it would be a good idea to increase the size of newstr accordingly (to twice that of str), i.e.
char newstr[2047]; // 2 * 1023 + terminator
...or, you know, make str smaller, depending on how long a string you want to support.
Thanks to Cool Guy for catching the superfluous & and newstr size implications.

"How does one successfully extract and manipulate a C string based on user input?"
You can use getchar() instead.
For example, you can store the user input in an array first. Then the problem becomes the same as if you did your 'char str[] = "Hello":
int index = 0
while((temp1 = getchar())!= '\n'){
str[index++] = temp1;
}

the following code
-complies cleanly
-checks and handles errors
-does the job
-doesn't use unneeded memory
(well actually) the logic could be a loop
that reads one char, outputs char, outputs space
or something similar if a trailing space is a problem
then the input buffer could be a single character
#include <stdio.h>
#include <stdlib.h> // exit, EXIT_FAILURE
#include <string.h>
int main()
{
// char str[] = "";
// there actually has to be room for the string
char str[100] = {'\0'};
printf("\nEnter a string: ");
if( 1 != scanf("%s", str) ) // arrays degenerate to pointer so no extra '&' needed
{ // then scanf failed
perror( "scanf failed" );
exit( EXIT_FAILURE );
}
// implied else, scanf successful
printf("\nYou typed: %s \n", str);
// there is no need to keep the modified string in memory
// when all that will be done is print it
int i = 0; // loop counter
printf("\nExpanded String: ");
for (i = 0; i < strlen(str); i++)
{
printf("%c", str[i]);
if( i < (strlen(str)-1) )
{ // then another char will follow
printf( " " );
}
else
{
printf( "\n" );
} // end if
} // end for
return 0;
} // end function: main

Related

Something weird happens when I try to get user input and print out strings

I'm playing around with user input and printing strings.
Whenever I run the code, the last string that I am trying to print is being glitched and doesn't print out correctly.
my code is:
#include <stdio.h>
int main() {
char inputRoses[] = "";
char inputViolets[] = "";
char inputAnd[] = "";
char roses[] = "Roses are: ";
char violets[] = "Violets are: ";
char and[] = "and: ";
printf("\n%s", roses);
scanf("%s", inputRoses);
printf("\n%s", violets);
scanf("%s", inputViolets);
printf("\n%s", and);
scanf("%s", inputAnd);
return 0;
}
Got this in the console:
Roses are: red
Violets are: blue
ue
I also tried this:
#include <stdio.h>
int main() {
char inputRoses[] = "";
char inputViolets[] = "";
char roses[] = "Roses are: ";
char violets[] = "Violets are: ";
printf("\n%s", roses);
scanf("%s", inputRoses);
printf("\n%s", violets);
scanf("%s", inputViolets);
return 0;
}
But got this in the console:
Roses are: red
ed
You haven't allocated any memory for the scanned input. char inputRoses[] = "" is an array of one char that contains a null-termination character (value is 0)
You need to allocate some memory and then also limit scanf via a formatter to not overflow this memory space when writing the user input into the buffer.
#include <stdio.h>
int main() {
char inputRoses[50] = "";
char inputViolets[50] = "";
char inputAnd[50] = "";
char roses[] = "Roses are: ";
char violets[] = "Violets are: ";
char and[] = "and: ";
printf("\n%s", roses);
scanf("%49s", inputRoses);
printf("\n%s", violets);
scanf("%49s", inputViolets);
printf("\n%s", and);
scanf("%49s", inputAnd);
return 0;
}
Scanf will now limit the the size of the user's input to fit in the memory available for the input buffers. We use the size of the buffer minus one in order to allow for a null terminator at the end of the string.
Results are like:
$ ./a.out
Roses are: red
Violets are: blue
and: stackoverflow has a big cazoo!
You are trying to put many characters in one slot. You must create enough slots in memory for the maximum characters entered. It is also enough to use one input array as buffer unless you want to use them again in the code. Even if it is so, you better use a single input buffer and copy the entered characters to their final destination using strncpy library function.
#include <stdio.h>
int main() {
char input[20]; // Must define the size (of character slots in memory) depending on the max possible input
char roses[] = "Roses are: ";
char violets[] = "Violets are: ";
printf("\n%s", roses);
scanf("%s", input);
printf("\n%s", violets);
scanf("%s", input);
return 0;
}
You should initialize your empty arrays like This:
char inputRoses[60] = "";
char inputViolets[50] = "";
char inputAnd[40] = "";
and your problem solved
this happens because you are declaring an empty character array rather you have to specify the size of your character array and if you want to get dynamic size area then use character pointers.

Code not letting me input and ends immediately

I have created a function that reverses all the words in a sentence, meaning that if the input is "Hello World" the output is supposed to be "World Hello". The code below is the function.
char* reversesentence(char sent[]) {
int lth = strlen(sent);
int i;
for(i = lth -1; i >= 0; i--) {
if(sent[i] == ' ') {
sent[i] = '\0';
printf("%s ", &(sent[i]) + 1);
}
}
printf("%s", sent);
}
In the main I am trying to ask the user for the sentence and calling the function in the main.
int main(void)
{
char sentence[2000];
printf("Please enter the sentence you want to be reversed.\n");
scanf("%s", sentence);
reversesentence(sentence);
printf("%s", sentence);
}
It seems that the array is only storing the first word of the sentence only.
Output:
Please enter the sentence you want to be reversed.
hello my name is
hellohello
Process finished with exit code 0`
Can someone help me fix this please? Searched online and found nothing useful.
scanf stops reading when it occurs whitespace,tabs or newline.
Matches a sequence of non-white-space characters; the next pointer
must be a pointer to character array that is long enough to hold the
input sequence and the terminating null byte ('\0'), which is added
automatically. The input string stops at white space or at the maximum
field width, whichever occurs first.
Thus you are not reading the entire string as you input.
Try using fgets as below.
fgets(sentence, sizeof(sentence), stdin);
Note fgets appends \n to end of the string. see how to trim the
new line from
fgets
You have two problems
as it was already said you only read one word using scanf
reversesentence just replace all spaces by a null character, so even you read a full line you cut it at the first space. so if you enter "hello world" the result will be "hello", and if you enter " hello world" the result will be an empty string
The simple way is to read words using scanf in a loop until it returns EOF, memorizing them, to at the end produce the list of words returned
For instance :
#include <stdlib.h>
#include <string.h>
int main()
{
size_t len = 0;
char * result = 0;
char word[256];
while (scanf("%256s", word) != EOF) {
if (result == 0) {
result = strdup(word);
len = strlen(word);
}
else {
size_t l = strlen(word);
char * r = malloc(len + l + 2);
strcpy(r, word);
r[l] = ' ';
strcpy(r + l + 1, result);
free(result);
result = r;
len += l + 1;
}
}
puts(result);
free(result);
return 0;
}
The reading finishes at the end of the input (^d under a linux shell), the words can be given on several lines.
With the input
hello world
how
are you
?
that prints
? you are how world hello

Which is the best way in this case to extract the substring from a string which is inputted by the user in C

Let's say I have the following string stored in char *m;
char *m = "K: someword\r\n";
The m will be inputed by the user so the user will write in the console:
K: someword\r\n
The someword can have different length, while K: \r\n will always be the same.
Now my question is, which is the best way after I read this input to extract someword from it and save it into a new char* variable?
Use sscanf() like this:
#include <stdio.h>
int main (void)
{
char buffer [50], k, return_car, new_line;
int n = sscanf ("K: someword\r\n", "%c: %s%c%c", &k, buffer, &return_car, &new_line);
printf ("The word is \"%s\". sscanf() read %d items.\n", buffer, n);
return 0;
}
Output:
The word is "someword". sscanf() read 4 items
Since both the substrings we aren't interested in ("K: " and "\r\n") are of fixed length, you can do this:
char *s;
size_t len = strlen(m);
s = malloc(len);
strcpy(s, m + 3);
s[len - 4] = 0;
printf("%s\n", s);
free(s);
Note that I declared a new char * variable to copy to since m is in read-only memory, and that robust code would handle the case where malloc failed and returned NULL.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main() {
char *m = "K: someword\r\n";
const size_t someword_len = strlen(&m[3]);
char *someword = malloc(someword_len);
if (someword == NULL) { fprintf(stderr, "Malloc error\n"); abort(); }
memcpy(someword, &m[3], someword_len - 2);
someword[someword_len - 1] = '\0';
puts(someword);
free(someword);
}
You assume that string m always starts with "K: " (that's 3 characters) and ends with "\r\n" (that's two characters).
I believe strlen(m) will be faster then strchr(m, '\r') or strrchr(m, '\r') on most platforms
After you have the length of the string, using memcpy instead of strcpy will be faster.
Remember to null terminate your string
Remember to handle errors.

How to input strings into an array in C?

I tried to get the inputs(strings) from user and store them in an array.But after I ran this code, the program instantly crashed.
#include <stdio.h>
int main() {
int i;
char *word[3];
for(i=0;i<3;i++)
{
printf(" Enter a word: ");
scanf("%s", &word[i]);
}
printf("%s ", word[0]);
return 0;
}
In this line:
scanf("%s", &word[i]);
You need to make sure word[i] is pointing somewhere, and has enough space to occupy the string entered. Since word[i] is a char * pointer, you need to at some time allocate memory for this. Otherwise, it is just a dangling pointer not pointing anywhere.
If you want to stick with scanf(), then you can allocate some space beforehand with malloc.
malloc() allocates requested memory on the heap, then returns a void* pointer at the end.
You can apply malloc() in your code like this:
size_t malloc_size = 100;
for (i = 0; i < 3; i++) {
word[i] = malloc(malloc_size * sizeof(char)); /* allocates 100 bytes */
printf("Enter word: ");
scanf("%99s", word[i]); /* Use %99s to avoid overflow */
/* No need to include & address, since word[i] is already a char* pointer */
}
Note: Must check return value of malloc(), because it can return NULL when unsuccessful.
Additionally, whenever you allocate memory with the use of malloc(), you must use free to deallocate requested memory at the end:
free(word[i]);
word[i] = NULL; /* safe to make sure pointer is no longer pointing anywhere */
Another approach without scanf
A more proper way to read strings should be with fgets.
char *fgets(char *str, int n, FILE *stream) reads a line from an input stream, and copies the bytes over to char *str, which must be given a size of n bytes as a threshold of space it can occupy.
Things to note about fgets:
Appends \n character at the end of buffer. Can be removed easily.
On error, returns NULL. If no characters are read, still returns NULL at the end.
Buffer must be statically declared with a given size n.
Reads specified stream. Either from stdin or FILE *.
Here is an example of how it can be used to read a line of input from stdin:
char buffer[100]; /* statically declared buffer */
printf("Enter a string: ");
fgets(buffer, 100, stdin); /* read line of input into buffer. Needs error checking */
Example code with comments:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NUMSTR 3
#define BUFFSIZE 100
int main(void) {
char *words[NUMSTR];
char buffer[BUFFSIZE];
size_t i, count = 0, slen; /* can replace size_t with int if you prefer */
/* loops only for three input strings */
for (i = 0; i < NUMSTR; i++) {
/* read input of one string, with error checking */
printf("Enter a word: ");
if (fgets(buffer, BUFFSIZE, stdin) == NULL) {
fprintf(stderr, "Error reading string into buffer.\n");
exit(EXIT_FAILURE);
}
/* removing newline from buffer, along with checking for overflow from buffer */
slen = strlen(buffer);
if (slen > 0) {
if (buffer[slen-1] == '\n') {
buffer[slen-1] = '\0';
} else {
printf("Exceeded buffer length of %d.\n", BUFFSIZE);
exit(EXIT_FAILURE);
}
}
/* checking if nothing was entered */
if (!*buffer) {
printf("No string entered.\n");
exit(EXIT_FAILURE);
}
/* allocate space for `words[i]` and null terminator */
words[count] = malloc(strlen(buffer)+1);
/* checking return of malloc, very good to do this */
if (!words[count]) {
printf("Cannot allocate memory for string.\n");
exit(EXIT_FAILURE);
}
/* if everything is fine, copy over into your array of pointers */
strcpy(words[count], buffer);
/* increment count, ready for next space in array */
count++;
}
/* reading input is finished, now time to print and free the strings */
printf("\nYour strings:\n");
for (i = 0; i < count; i++) {
printf("words[%zu] = %s\n", i, words[i]);
free(words[i]);
words[i] = NULL;
}
return 0;
}
Example input:
Enter a word: Hello
Enter a word: World
Enter a word: Woohoo
Output:
Your strings:
words[0] = Hello
words[1] = World
words[2] = Woohoo
There seems to be a bit of confusion in this area. Your primary problem is you are attempting to write each word to the address of each of pointers you declare with char *word[3];. (not to mention you have no storage allocated at the location pointed to by each pointer -- but you never get there as you attempt to write to the address of each pointer with &word[i] rather than to the pointer itself)
While you can use scanf you will quickly run into one of the many pitfalls with taking user input with scanf that plague all new C programmers (e.g. failing to handle the '\n' left in the input buffer, failing to handle whitespace in strings, failing to limit the number of characters read/written, failing to validate the read or handle EOF, etc...)
A better approach is to simply use fgets and then trim the '\n' that fgets read and includes in the buffer to which it stores the string. A simple example would be:
#include <stdio.h>
#include <string.h>
#define NWDS 3 /* declare a constant for the maximum number of words */
int main (void) {
int i, n = 0;
char word[NWDS][50] = { "" }; /* provide storage or allocate */
for (i = 0; i < NWDS; i++) { /* for a max of NWDS */
printf ("Enter word : "); /* prompt */
if (!fgets (word[i], sizeof word[i], stdin)) /* read/validate */
break; /* protect against EOF */
size_t len = strlen (word[i]); /* get length */
if (word[i][len-1] == '\n') /* check for trailing '\n' */
word[i][--len] = 0; /* overwrite with nulbyte */
}
n = i; /* store number of words read */
putchar ('\n'); /* make it pretty */
for (i = 0; i < n; i++) /* output each word read */
printf (" word[%d] : %s\n", i, word[i]);
#if (defined _WIN32 || defined _WIN64)
getchar(); /* keep terminal open until keypress if on windows */
#endif
return 0;
}
Go ahead and cancel input at any time by generating an EOF during input (ctrl + d on Linux or ctrl + z on windoze), you are covered.
Example Use/Output
$ ./bin/wordsread
Enter word : first word
Enter word : next word
Enter word : last word
word[0] : first word
word[1] : next word
word[2] : last word
Looks things over, consider the other answers, and let me know if you have further questions.
char *word[3]; // <-- this is an array of 3 dangling pointers, of type char*
// they still point nowhere, we later need to set them to some allocated location.
...
for(i=0;i<3;i++) {
word[i] = malloc(some_max_size * sizeof(char)); // <-- allocate space for your word
printf(" Enter a word: ");
scanf("%s", word[i]); // <-- not &word[i]; word[i] is already a char* pointer
}
You are declaring word as array of pointer (char *word[3];). You have to allocate memory to store data. Allocate memory with malloc or similar functions before assigning values.
Yes the code crashes because declaring an array of character
pointers is not enough, you need to set the pointers to point
to memory where the strings can be stored.
E.g.
const int maxLen = 32;
char* word[3] = {NULL,NULL,NULL};
word[i] = malloc(maxLen);
then read the string from keyboard, to ensure that the string is not too
long use fgets and maxLen:
printf("Enter a word:");
fgets(word[i],maxLen,stdin);
#include <stdio.h>
int main(){
int n;
int i=0;
scanf("%d",&n);
char arr[n];
while(n>i){
scanf("%s",&arr[i]);
i+=1;
}
while(n-i<n){
printf(" %c ",arr[n-i]);
i-=1;
}
}
The code char *word[3] made a 3-element array of pointers!
See, you have basically created a character array of pointers, so you cannot put a "string" into each one of them, because the type of a pointer variable is long hexadecimal.

Strings in C Language

How can you code this in C language if the output is like this? I need strings format of the code because our topic is strings.
#include <stdio.h>
#include <stdlib.h>
void main()
{
char my_string[50];
printf("Enter a word:");
scanf("%s", my_string);
printf("Enter a word:");
scanf("%s", my_string);
// Some unknown code here...
// this part is my only problem to solve this.
getch();
}
Output:
Hello -> (user input)
World -> (user input)
HWeolrllod -> (result)
Okay, you need to do some investigating. We don't, as a general rule, do people's homework for them since:
it's cheating.
you'll probably get caught out if you copy verbatim.
it won't help you in the long run at all.
The C library call for user input that you should use is fgets, along the line of:
char buffer[100];
fgets (buffer, sizeof(buffer), stdin);
This will input a string into the character array called buffer.
If you do that with two different buffers, you'll have the strings in memory.
Then you need to create pointers to them and walk through the two strings outputting alternating characters. Pointers are not an easy subject but the following pseudo-code may help:
set p1 to address of first character in string s1
set p1 to address of first character in string s1
while contents of p1 are not end of string marker:
output contents of p1
add 1 to p1 (move to next character)
if contents of p2 are not end of string marker:
output contents of p2
add 1 to p2 (move to next character)
while contents of p2 are not end of string marker:
output contents of p2
add 1 to p2 (move to next character)
Translating that into C will take some work but the algorithm is solid. You just need to be aware that a character pointer can be defined with char *p1;, getting the contents of it is done with *p1 and advancing it is p = p + 1; or p1++;.
Short of writing the code for you (which I'm not going to do), there's probably not much else you need.
void main()
{
char my_string1[50],my_string2[50]; int ptr;
ptr=0;
printf("Enter a word : ");
scanf("%s",my_string1);
printf("enter a word");
scanf("%s",my_string2);
while(my_string1[ptr]!='\0' && my_string2[ptr]!='\0')
{
printf("%c%c",my_string1[ptr],my_string2[ptr]);
ptr++;
}
if(my_string1[ptr]!='\0')
{
while(my_string1[ptr]!='\0')
{ printf("%c",my_string1[ptr]);
ptr++;
}
}
else
{
while(my_string2[ptr]!='\0')
{printf("%c",my_string2[ptr]);
ptr++;
}
}
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void main()
{
char my_string1[50],my_string2[50];
int i,l1=1,l2=0;
printf("Enter a word:");
scanf("%s", my_string1);
printf("Enter a word:");
scanf("%s", my_string2);
l1=strlen(my_string1); /* Length of 1st string */
l2=strlen(my_string2); /* Length of 2nd string */
if(l1==l2)
{
for(i=0;i<l1;i++)
{
printf("%c%c",my_string1[i],my_string2[i]);
}
}
else
{
printf("Length of the entered strings do not match");
}
}
This is your required code.
You can see that output needs to be a String containing all chars of User String1 and User String2 one by one...
You can do this like...
//add #include<String.h>
int l1=strlen(s1);
int l2=strlen(s2);
if(l1!=l2)
{
printf("length do not match");
return 0;
}
char ansstr[l1+l2];
int i,j=0,k=0;
for(i=0;i<l1+l2;i=i+2)
{
ansstr[i]=s1[j];
ansstr[i+1]=s2[k];
j++;
k++;``
}
//ansstr is your answer
Ok, here's your code. Come on guys, if he asked here it means he can't solve this.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
char str1[] = "abcdefghijklmopq";
char str2[] = "jklm";
int len1 = strlen(str1);
int len2 = strlen(str2);
int c1 = 0, c2 = 0;
int max = (len1 > len2) ? len1 : len2 ;
char *result = malloc(len1 + len2);
for(c1 = 0; c1 <= max; c1++) {
if(c1 < len1)
result[c2++] = str1[c1];
if(c1 < len2)
result[c2++] = str2[c1];
}
result[c2] = 0;
printf("\n%s\n", result);
return 0;
}
Basically the loop picks up a character from str1 and appends it to result. Then it picks a character, which stands in the same position as the first from str2 and appends it to result, just as before. I increment c2 by 2 every time because I'm adding 2 chars to result. I check if c1 is bigger that the length of the strings because I want to copy only the characters in the string without the terminating \0. If you know that your strings have the same length you can omit these ifs.

Resources