Putting users input consisting of numbers separated by commas into an array? - c

I am taking in 10 numbers from the user (user enters them at a prompt, and the numbers are separated by commas, as so: 245645, -243, 4245). How can I put these elements into an array? As shown below, I have used scanf which does not work as I had hoped. Any suggestions would be appreciated.
//User will pass ten numbers, separated by commas. This is to be put into an array.
#include <stdio.h>
int main ()
{
int A[10]; // array to contain in users input.
printf("Enter your numbers: ");
scanf("%d", &A[10]);
return 0;
}

You have to consume the comma as well in scanf:
for(int i=0; i<10; i++) { /* for each element in A */
if(0==scanf("%d,", &A[i])) { /* read a number from stdin into A[i] and then consume a commma (if any) */
break; /* if no digit was read, user entered less than 10 numbers separated by commas */
/* alternatively error handling if fewer than 10 is illegal */
}
}

I won't write the whole thing for you.
But I can definitely help.
One of the ways to do that will be:
Get a string that contains 10 comma-separated numbers: fgets() may be?
Validate the string, trim white-spaces as well, makes life easier
Pick out a number from string: strtol() may be?
Search for a ',' character in the string, and set pointer to the next index after ',': strchr() may be?
Repeat steps 3 and 4 for a total of 10 times (from here, 9 times actually)
Print the numbers
The code below would do half of your job. The only remaining part would be to get string from user and validate it.
The intention to have a string declared and initialised upfront is to put more emphasise on actual parsing of data which appear complicated to beginners (no offence).
Before we look at the code below, lets read a few things first.
You might want to take a look at the man page for strtol() function
You might want to take a look at the man page for fgets() function, which is not used in the code below, but you may end-up using it to achieve step 1.
I already concede the fact that this may not be the best way to achieve it, and I would happily agree that this code below can be made better in thousand ways by adding various error check, but I leave that to you to explore and implement.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(void)
{
int i = 0, j = 0;
char *Str = "1,11,21,1211,111221,312211,1234,4321,123,789";
char *ptr;
long ret;
long array[10] = { [0 ... 9] = 0 };
// So, lets assume step 1 and 2 are taken care of.
// Iterate though the data for 10 times
for(i = 0; i < 10; i++)
{
ret = strtol(Str, &ptr, 10);
// Check if its a number
if(ret != 0)
{
// Its is a number!
// Put it in the array
array[j] = ret;
// Increment the index so that next number will not over-write the existing one
j++;
// Find the next ',' in the string
Str = strchr(Str, ',');
if(Str == NULL)
{
// Handle this condition that there are no more commas in the string!
break;
}
// Assuming that the ',' is found, increment the pointer to index next to ','
Str++;
}
}
// Print the array
for(i = 0; i < j; i++)
printf("%ld\n", array[i]);
}
This prints the following output:
1
11
21
1211
111221
312211
1234
4321
123
789
Hope I have got you started, Good luck.

Related

How to fix code that extracts even numbered index values in an array of a sentence and combines it with odd numbered index values?

Basically, my code is supposed to encrypt a sentence(or word) by taking out all the even numbered index values(starting from 0) and the odd numbered index values and placing the even index values before the odd index values.
For example, a word like "test" (0)t(1)e(2)s(3)t should be printed as (0)t(2)s(1)e(3)t or "tset". There aren't supposed to be any numbers printed, I just used them to show the odd and even index values.
My code works sometimes, depending on where it is run. I seem to be getting differing results between code blocks and an online compiler I tried. I suspect there must be a larger issue to blame for this inconsistency. Can anyone help me to see what I'm doing wrong so I can finally understand and rectify my errors?
I have tried using one counter to input both even and odd index values into one array but I was having errors with that as well so I decided to put them into separate arrays and then use strcat to combine them. Is there a way to make it work with the method I've shown in my code or should I go back to the previous method?
#include <stdio.h>
#include <string.h>
#define SIZE 1000
int main()
{
char message[SIZE];
char even[SIZE];
char odd[SIZE];
int length,j=0;
printf("Enter a word or sentence.\n");
fgets(message,SIZE,stdin);
printf("Your message is: %s\n",message);
message[strcspn(message, "\n")] = 0;
length=strlen(message);
printf("The length of the message is: %d\n",length);
for(int i=0;i<length;i+=2){
even[i/2]=message[i];
// printf("%c\n",even[i/2]);
}
for(int i=1;i<length;i+=2){
odd[j]=message[i];
j++;
}
printf("The even letters are: %s\n",even);
printf("The odd letters are: %s\n",odd);
strcat(even,odd);
printf("%s",even);
/*printf("\nFInalyy.");
for(i=0;i<=count;i++)
for(j=i+1;j<=count;j++){
if(strcmp(allmessages[i],allmessages[j])>0){
strcpy(temp,allmessages[i]);
strcpy(allmessages[i],allmessages[j]);
strcpy(allmessages[j],temp);
}
}
printf("The original messages in alphabetical order are: ");
for(i=0;i<=count;i++)
puts(allmessages[i]);*/
return 0;
}
It works perfectly when I type in words like "test" or "sentence". Sometimes I type in sentences like "this is a test sentence" and it would work perfectly then one time it would print out some random garbage letters along with the encrypted sentence. I would like to know how to fix this and to understand why it works perfectly with the same entry a few times then just stops. I used https://www.onlinegdb.com/online_c_compiler to test it the last few times so my results are based on that.
Successful Result:
Unsuccessful Result using the same entry:
You can take a slightly shorter approach by simply using two indexes to build your encrypted string (like evenstart and oddstart) based on the total length of the message entered by the user. evenstart = 0; and oddstart = (msglen + 1) / 2;
Then just loop over the characters in the message entered by the user writing even characters at encrypt[evenstart++] and odd characters at encrypt[oddstart++]. (don't forget to nul-terminate encrypt if you will be using it as a string for output purposes.
Putting it together you could do:
#include <stdio.h>
#include <string.h>
#define MAXC 1024
int main (void) {
char message[MAXC],
encrypt[MAXC];
size_t len, evenstart = 0, oddstart;
fputs ("enter message: ", stdout);
if (!fgets (message, MAXC, stdin)) { /* validate message entered */
fputs ("(user canceled input)\n", stdout);
return 1;
}
message[(len = strcspn(message, "\r\n"))] = 0; /* trim '\n', get len */
oddstart = (len + 1) / 2; /* get oddstart (add 1 before divide) */
for (size_t i = 0; i < len; i++) /* loop over each char */
if (i & 1) /* if odd, write char at oddstart */
encrypt[oddstart++] = message[i];
else /* if even, write at evenstart */
encrypt[evenstart++] = message[i];
encrypt[len] = 0; /* nul-terminate */
printf ("message : '%s'\nencrypt : '%s'\n", message, encrypt);
}
(note: you can use i % 2 to check even/odd if you like, or simply i & 1 -- in binary, if the ones-bit is 1 it's odd, otherwise its even -- up to you)
Example Use/Output
$ ./bin/encrevenodd
enter message: tes
message : 'tes'
encrypt : 'tse'
$ ./bin/encrevenodd
enter message: test
message : 'test'
encrypt : 'tset'
$ ./bin/encrevenodd
enter message: tests
message : 'tests'
encrypt : 'tsset'
$ ./bin/encrevenodd
enter message: my dog has fleas
message : 'my dog has fleas'
encrypt : 'm o a laydghsfes'
Look things over and let me know if you have questions.
Strings in C are terminated by the null byte ('\0' or ascii value 0) just so it knows where the string ends. Since the even and odd character arrays were not terminated by the null byte, strcat does not know when to stop appending characters. So the garbage values you see is because strcat keeps appending characters until you luckily find a 0 in memory.
Strings in C do not know their length, they're just pointers. Strings must be terminated with a null character in order for functions like printf and strlen to know when to stop.
char even[SIZE];
char odd[SIZE];
At this point even and odd both contain whatever garbage was in memory at that time.
for(int i=0;i<length;i+=2){
even[i/2]=message[i];
}
for(int i=1;i<length;i+=2){
odd[j]=message[i];
j++;
}
Now the beginning of odd and even have been filled in, but they were not null terminated.
printf("The even letters are: %s\n",even);
printf("The odd letters are: %s\n",odd);
These will start at where even and odd point, print the characters you've put in there, and then keep on printing whatever garbage was in memory until they happen to hit a null character.
The fix is to either zero out the memory with memset.
memset(even, '\0', SIZE);
memset(odd, '\0', SIZE);
Or ensure that even and odd are null terminated once you're done with them.
for(i=0;i<length;i+=2){
even[i/2]=message[i];
}
even[i/2] = '\0';
for(i=1;i<length;i+=2){
odd[j]=message[i];
j++;
}
odd[j] = '\0';
Side note, even and odd loops can be done with the same technique.
for( i=0,j=0; i<length; i+=2,j++ ) {
even[j]=message[i];
}
even[j] = '\0';
for( i=1,j=0; i<length; i+=2,j++ ) {
odd[j]=message[i];
}
odd[j] = '\0';
Then we can observe that the only difference is where we start reading message. That means we can put this in a function and always remember to null terminate the result.
void copy_every_other_character(const char *src, char *dst) {
int i,j,length = 0;
length = strlen(src);
for( i=0,j=0; i<length; i+=2,j++ ) {
dst[j] = src[i];
}
dst[j] = '\0';
}
copy_every_other_character(message, even);
copy_every_other_character(message+1, odd);
Adding 1 to message means copy_every_other_character will get a pointer to the second character of message and go on from there. If message is 01234 it will see 1234.

How to split string (character) and variable in 1 line on C?

How can I split character and variable in 1 line?
Example
INPUT
car1900food2900ram800
OUTPUT
car 1900
food 2900
ram 800
Code
char namax[25];
int hargax;
scanf ("%s%s",&namax,&hargax);
printf ("%s %s",namax,hargax);
If I use code like that, I need double enter or space for make output. How can I split without that?
You should be able to use code like this to read one name and number:
if (scanf("%24[a-zA-Z]%d", namax, &hargax) == 2)
…got name and number OK…
else
…some sort of problem to be reported and handled…
You would need to wrap that in a loop of some sort in order to get three pairs of values. Note that using &namax as an argument to scanf() is technically wrong. The %s, %c and %[…] (scan set) notations all expect a char * argument, but you are passing a char (*)[25] which is quite different. A fortuitous coincidence means you usually get away with the abuse, but it is still not correct and omitting the & is easy (and correct).
You can find details about scan sets etc in the POSIX specification of scanf().
You should consider reading a whole line of input with fgets() or POSIX
getline(), and then processing the resulting string with sscanf(). This makes error reporting and error recovery easier. See also How to use sscanf() in loops.
Since you are asking this question which is actually easy, I presume you are somewhat a beginner in C programming. So instead of trying to split the input itself during the input which seems to be a bit too complicated for someone who's new to C programming, I would suggest something simpler(not efficient when you take memory into account).
Just accept the entire input as a String. Then check the string internally to check for digits and alphabets. I have used ASCII values of them to check. If you find an alphabet followed by a digit, print out the part of string from the last such occurrence till the current point. And while printing this do the same with just a slight tweak with the extracted sub-part, i.e, instead of checking for number followed by letter, check for letter followed by digit, and at that point print as many number of spaces as needed.
just so that you know:
ASCII value of digits (0-9) => 48 to 57
ASCII value of uppercase alphabet (A-Z) => 65 to 90
ASCII value of lowercase alphabets (a-z)
=> 97 to 122
Here is the code:
#include<stdio.h>
#include<string.h>
int main() {
char s[100];
int i, len, j, k = 0, x;
printf("\nenter the string:");
scanf("%s",s);
len = strlen(s);
for(i = 0; i < len; i++){
if(((int)s[i]>=48)&&((int)s[i]<=57)) {
if((((int)s[i+1]>=65)&&((int)s[i+1]<=90))||(((int)s[i+1]>=97)&&((int)s[i+1]<=122))||(i==len-1)) {
for(j = k; j < i+1; j++) {
if(((int)s[j]>=48)&&((int)s[j]<=57)) {
if((((int)s[j-1]>=65)&&((int)s[j-1]<=90))||(((int)s[j-1]>=97)&&((int)s[j-1]<=122))) {
printf("\t");
}
}
printf("%c",s[j]);
}
printf("\n");
k = i + 1;
}
}
}
return(0);
}
the output:
enter the string: car1900food2900ram800
car 1900
food 2900
ram 800
In addition to using a character class to include the characters to read as a string, you can also use the character class to exclude digits which would allow you to scan forward in the string until the next digit is found, taking all characters as your name and then reading the digits as an integer. You can then determine the number of characters consumed so far using the "%n" format specifier and use the resulting number of characters to offset your next read within the line, e.g.
char namax[MAXNM],
*p = buf;
int hargax,
off = 0;
while (sscanf (p, "%24[^0-9]%d%n", namax, &hargax, &off) == 2) {
printf ("%-24s %d\n", namax, hargax);
p += off;
}
Note how the sscanf format string will read up to 24 character that are not digits as namax and then the integer that follows as hargax storing the number of characters consumed in off which is then applied to the pointer p to advance within the buffer in preparation for your next parse with sscanf.
Putting it altogether in a short example, you could do:
#include <stdio.h>
#define MAXNM 25
#define MAXC 1024
int main (void) {
char buf[MAXC] = "";
while (fgets (buf, MAXC, stdin)) {
char namax[MAXNM],
*p = buf;
int hargax,
off = 0;
while (sscanf (p, "%24[^0-9]%d%n", namax, &hargax, &off) == 2) {
printf ("%-24s %d\n", namax, hargax);
p += off;
}
}
}
Example Use/Output
$ echo "car1900food2900ram800" | ./bin/fgetssscanf
car 1900
food 2900
ram 800

How to fill an array without hitting enter in a for loop

I know this might seem a very noob question, but I am very confused at the moment. Is there any way to accept values from the user into an array without hitting enter every time ?
Like if the number of values to accept is 3, so the user can enter values as 5 25 45 and hit enter and it gets stored in the array as three separate values.
I am trying to do this with a for loop but it only accepts the next value once I hit enter.
This works
#include <stdio.h>
int main(void) {
int array[10];
printf("Enter 10 values separated by whitespace (enter, space, tab, ...)\n");
for (int k = 0; k < 10; k++) {
if (scanf("%d", array + k) != 1) /* error */;
}
return 0;
}
You have to save that line as a string, then parse it (split it up) with a different function. You should be able to look up how to do that. Try googling "parse string c" or something along those lines.
EDIT: pmg's solution is much simpler, and works for your purposes. I'd use that.
Use strtok!
Please remember to include string.h.
CharArrayToMatch will in this case be the input string from the user.
Let's for sake of example say that it is "1 2 3 4 5".
{1} will get the first number - 1 and make strtok "ready" for the read the rest of the string.
{2} prints the current token - replace this with whatever you want to do.
{3} as long as this does not return NULL, there are more tokens to process.
When we enter the loop, we will first print 1, then get the next number: 2, put it into tmp, then repeat the process with the other numbers. After 5, strtok will return NULL and we'll exit the loop.
// We split on spaces and get the pointer to the first token
char *tmp = strtok(CharArrayToMatch, " "); // {1}
while (tmp != NULL) {
// do whatever action you want to do instead of this - for instance: atoi!
printf("%s\n", tmp); // {2}
// Get the next token
tmp = strtok(NULL, " "); // {3}
}
Edit #1: added a few comments.
Edit #2: Please note that this solution actually handles a generic number of inputs.
Edit #3: quick attempt at making it clearer.

Having a hard time using getchar and storing characters

I am new to programming in C and still trying to learn all of the useful functions it provides in its libraries. In particular I'm trying to wrap my head around how to use getchar() for more than one character in a certain situation. I want to be able to have input from the console be something like:
11 2 34 100
I want to be able to distinguish between these entries(delimiter space I guess?), and add these numbers up. This is an assignment, so I was wondering if someone could give me a hint or point me in the right direction on how to go further with this. I would certainly appreciate it. This is what I have at the moment. Also, we're not supposed to make use of arrays here. This really threw me because I don't see any other way. Again any help or pointers in the right direction would go a long way!
int main()
{
int count = 0;
char input;
int wordCount = 0;
int numEntered = 0;
input = getchar();
while(input != '\n')
{
if(input != ' ')
{
count++;
}
input = getchar();
}
printf("Number of characters included in numbers %d\n", count);
return 0;
}
You can store two integers, one that is the running total, and one that is the current number.
If you encounter a digit that is not a space, multiply the current number by 10 and then add that digit to the current number.
If you encounter a space, add the current number to the running total, then reset the current number to 0.

Converting Character Array to Integer Array in C for ISBN Validation

I really hope someone can give a well explained example. I've been searching everywhere but can't find a proper solution.
I am taking an introduction to C Programming class, and our last assignment is to write a program which validates a 10 digit ISBN with dashes... The ISBN is inputted as a string in a CHAR array. From there I need to separate each digit and convert them into an integer, so I can calculated the validity of the ISBN. On top of that, the dashes need to be ignored..
My thought process was to create an INT array and then use a loop to store each character into the array, and pass it through the atoi() function. I also tried using an IF statement to check each part of the CHAR array to see if it found a dash. If it did find one, it would skip to the next spot in the array. It looked something like this:
int num[12], i = 0, j = 0, count = 0;
char isbn[12];
printf ("Enter an ISBN to validate: ");
scanf ("%13[0-9Xx-]%*c", &isbn);
do {
if (isbn[i] == '-') {
i++;
j++;
}
else {
num[i]= atoi(isbn[j]);
i++;
j++;
}
count++;
} while (count != 10);
But that creates a segmentation fault, so I can't even tell if my IF statement has actually filtered the dashes....
If someone could try and solve this I'd really appreciate that. The Assignment was due Dec 4th, however I got an extension until Dec 7th, so I'm pressed for time.
Please write out the code in your explanation. I'm a visual learner, and need to see step by step.
There's obviously a lot more that needs to be coded, but I can't move ahead until I get over this obstacle.
Thanks in advance!
First of all, your definition of isbn is not sufficient to hold 13 characters; it should therefore be 14 chars long (to also store the terminating '\0').
Second, your loop is overly complicated; three loop variables that maintain the same value is redundant.
Third, the loop is not safe, because a string might be as short as one character, but your code happily loops 10 times.
Lastly, converting a char that holds the ascii value of a digit can be converted by simply subtracting '0' from it.
This is the code after above improvements have been made.
#include <stdio.h>
int main(void)
{
int num[14], i;
char isbn[14], *p;
printf("Enter an ISBN to validate: ");
scanf("%13[0-9Xx-]%*c", &isbn);
// p iterates over each character of isbn
// *p evaluates the value of each character
// the loop stops when the end-of-string is reached, i.e. '\0'
for (p = isbn, i = 0; *p; ++p) {
if (*p == '-' || *p == 'X' || *p == 'x') {
continue;
}
// it's definitely a digit now
num[i++] = *p - '0';
}
// post: i holds number of digits in num
// post: num[x] is the digit value, for 0 <= x < i
return 0;
}

Resources