How do I a split a line of integers into array? [closed] - c

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
If a user inputted:
1 2 3 4 5 0
How would I transform it into an array with 5 elements (The 0 integer indicates termination)? Also, in the code I need to ensure it works for up to 500 integers.
I have no clue how to proceed. I am thinking of using gets and saving it into an allocated space:
char *ptr;
ptr = malloc(sizeof(char) * 1000);
fgets(ptr, sizeof(char)*1000, stdin);
The problem here is I am not sure how to allocate the space as each digit will be saved as a character and each integer may have different number of digits.
Afterwards, I am not sure how to split it into array.
Could someone advise me on how to continue or if my method is not good?
I know I have not done a lot but I am really confused. I have looked up on gets(), fgets(), scanf(), fscanf(), and am still not sure.
Thanks!

You can parse the line input by the user with sscanf() or strtol():
#include <stdio.h>
int main() {
char buf[256];
int array[5];
if (fgets(buf, sizeof buf, stdin)) {
if (sscanf(buf, "%d%d%d%d%d", &array[0], &array[1], &array[2], &array[3], &array[4]) == 5) {
// array has the 5 numbers input by the user.
printf("%d %d %d %d %d\n", array[0], array[1], array[2], array[3], array[4]);
}
}
return 0;
}
For generic code that works up to 500 numbers, you can just use scanf() in a loop:
#include <stdio.h>
int main() {
int array[500];
int i, n;
for (n = 0; n < 500; n++) {
if (scanf("%d", &array[n]) != 1) {
printf("invalid input\n");
return 1;
}
if (array[n] == 0) {
// 0 indicates termination
break;
}
}
// the array has n valid non-zero numbers
printf("The numbers are:\n");
for (i = 0; i < n; i++) {
printf(" %d\n", array[i]);
}
return 0;
}

You could use a character array with a combination of fgets() and strtok().
First declare a character array str and set a flag variable.
char str[100];
int flag=1;
flag may be made 0 when input 0 is found.
As long as flag is 1 use fgets() to read a line of input (provided fgets() is successful) as in
while(flag==1 && fgets(str, sizeof(str), stdin)!=NULL)
{
.....
.....
}
Now inside this loop, use strtok() to tokenize the string in str using space and \n as delimiters. \n is made a delimiter because fgets() reads in the trailing \n to str as well.
for(ptr=strtok(str, " \n"); ptr!=NULL; ptr=strtok(NULL, " \n"))
{
n=atoi(ptr);
if(n==0)
{
flag=0;
break;
}
printf("\n%d", n);
}
Convert the tokens produced by strtok() to integers. I used atoi() for brevity but it is not the best way. strtol() might be a good idea. See here.

I would suggest something like this
#include "rlutil.h" //a good library similar to conio.h or it's Linux equivalent but cross-platform. You have to include it manually and download it at github.
int i = 0;
int num = 1;
char input;
int array[255];
for (i = 0; num = 0; i++)
{
input = getchar();
num = input - '0';
array[i] = num;
printf("%i ", num);
}
Just pay attention to the size of the array.
Furthermore you could parse the string you got with fgets with strtok. If you want I can edit this post later and include this variant.

Related

C: loop over fgets digit by digit lean for strange behavior [duplicate]

This question already has answers here:
C programming: print only int from fgets
(7 answers)
Closed 5 years ago.
I want to implement simple task:
I have single line input with numbers:
2 1 2 3
And i want to print it so currently this works fine for most of scenarios:
char str[512];
for (i = 0; i < (strlen(str)); i++)
{
if (str[i] != '\0' && !isspace(str[i]))
{
int num = atoi(&str[i]);
printf("%d ", num);
}
}
Now in case my input is with number with mote then one digit things start to mess.
For example:
2 12
In this case i can see that i have this input:
2 12 2
So in case i have number > 9 i can just raise i by 1:'
if (i > 9)
i++;
And in case my number is with 3 digits i can just do i+=2 but is there is another solution maybe that is more 'clean' ?
EDIT
fgets(str, sizeof str, stdin);
char *ptr;
long ret;
for (i = 0; i < (strlen(str)); i++)
{
if (str[i] != '\0' && !isspace(str[i]))
{
ret = strtol(str[i], &ptr, 10);
printf("%ld\n", ret);
}
}
You already found out what's wrong with your solution. The idea you present is bad, what if the string contains something like 01? This is two characters, but still smaller than 10.
There are several possibilities to do better, I can think of two approaches immediately:
instead of atoi(), use strtol() (you should anyways). strtol() has a parameter endptr -- pass it the address of a char * pointer, then this pointer will point to the first character that wasn't converted. To use this, you must probably rewrite your loop to use pointers. Here's an example:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
char str[512] = "2 15 42 7 11";
int main(void)
{
for (const char *c = str; *c;)
{
if (!isspace(*c))
{
char *endptr;
long num = strtol(c, &endptr, 10);
if (endptr == c) exit(1); // nothing was converted, just error out here
printf("%ld\n", num);
c = endptr;
}
else
{
++c;
}
}
}
Even simpler, if it doesn't matter to destroy your input string in the course, use strtok() (see the manpage for how it works) to split your strings at the whitespace, like strtok(str, " \t\n") in the first iteration and strtok(0, " \t\n") in the subsequent iterations. Then you can just convert the parts you get from strtok().

Trying to check if a number is a palindrome through the use of strings [duplicate]

This question already has answers here:
How do I check if a number is a palindrome?
(53 answers)
Closed 5 years ago.
I am trying to check if an input number is a palindrome. I am doing it through strings rather than ints. So, I am taking in a string and reversing it into another string. However, when I use the string compare function it does not give me 0, stating that the strings are not the same. Even when I put in for example "1001", both the input and reverse strings displays 1001. I have figured it out with other methods but am trying to understand what is wrong with this one in specific.
#include <stdio.h>
#include <string.h>
int main(void)
{
char input[100];
char reverse[100];
int numLen = 0;
printf("Enter a number\n");
fgets(input, 100, stdin);
printf("The number is: %s\n", input);
numLen = strlen(input) - 1;
printf("Length of string is: %d\n", numLen);
for (int i = 0; i < numLen; i++)
{
reverse[i] = input[numLen - 1 - i];
if (i == numLen - 1)
{
reverse[i + 1] = '\0';
}
}
printf("The reverse number is: %s\n", reverse);
printf("The original number is: %s\n", input);
int result = strcmp(input, reverse);
printf("Result of strcmp gives us: %d\n", result);
if (strcmp(input, reverse) == 0)
{
printf("These numbers are palindromes\n");
}
else
{
printf("These numbers are not palindromes\n");
}
return 0;
}
The problem is you are not handling the strings properly. You should overwrite the '\n' with \0.
...
char input[100];
char reverse[100];
int numLen = 0;
printf("Enter a number\n");
fgets(input, 100, stdin);
printf("The number is: %s\n", input);
input[strcspn(input,"\n")]='\0'; // getting the length of the
// string without `\n`
// and overwriting with `\0`
numLen = strlen(input) ; // now you don't need to put the -1
printf("Length of string is: %d\n", numLen);
for (int i = 0; i < numLen; i++)
{
....
Apart from these two changes everything else remains the same. You were reversing it all right. And then you used strcmp right way. But the extra \n is removed in the code I have shown.
(still) Why it works?
Now to give you a better idea. You formed the reversed string alright. But the original string has \n within itself.
printf("The reverse number is: (%s)\n", reverse);
printf("The original number is: (%s)\n", input);
In the previous program you just do write these two lines. You will understand where you went wrong.
On giving input 1001Enter it gives this output.
The reverse number is: (1001)
The original number is: (1001
)
What is strcspn doing?
I have using strcspn function got the length without \n and overwriting it with \0.
0 1 2 3 4 5 --> indices
1 0 0 1 \n \0 --> strcspn(input,"\n") returns 4.
1 0 0 1 \0 \0 --> input[strcspn(input,"\n")]='\0'
You can do simply like this without the copying and everything.
Without extra memory - in place palindrome checking
bool checkPal(const char *s){
for(int i = 0, j= strlen(s)-1; i< strlen(s) && j>=0 ; i++)
if(s[i] != s[j])
return false;
return true;
}
int main(void)
{
char input[100];
char reverse[100];
printf("Enter a number\n");
if( fgets(input, 100, stdin) )
printf("The number is: %s\n", input);
input[strcspn(input,"\n")]='\0';
int numLen = strlen(input) ;
printf("Length of string is: %d \n", numLen);
printf("These numbers are %spalindromes\n", checkPal(input)?"not ":"");
return 0;
}
A more succinct way to write the checkPal() would be,
bool checkPal(const char *first){
const char *last = first + strlen(first);
while (first < last) {
if (*first++ != *--last) {
return false;
}
}
return true;
}
last points to the \0 character. Subtraction is necessary before we start doing comparison. To get a clear idea of what happens you have to know the precedence and few rules.
The first<last part is obvious. We are comparing till we reach a point where we first > last (For even length strings) or first = last (for odd length strings).
The if is a bit tricky. *first++ there are two operators involved. * (indirection) and ++(post increment).
And precedence of ++ is higher than de-reference *.
So *first++ will be - first is incremented. Then you might think that we are missing one character very first time but that's not the case. Value of a postfix expression is the value before we do first++. So now you have the first character.
Same way *--last will have the same effect except the value of the prefix expression is the value after the operation. So you are considering the last character.
If they matches we continue. first and last already contain the modified value. We repeat the same logic for rest of the characters in the smaller sub-string.
If a mismatch occurs then we return immediately. (Because it's not a palindrome).
Sorry, my bad. Try this:
#include <stdio.h>
#include <string.h>
// A function to check if a string str is palindrome
void isPalindrome(char str[])
{
// Start from leftmost and rightmost corners of str
int l = 0;
int h = strlen(str) - 1;
// Keep comparing characters while they are same
while (h > l)
{
if (str[l++] != str[h--])
{
printf("%s is Not Palindromen", str);
return;
}
}
printf("%s is palindromen", str);
}
// Driver program to test above function
int main()
{
isPalindrome("abba");
isPalindrome("abbccbba");
isPalindrome("geeks");
return 0;
}
Does this one work?
A variant, recursive version that has no more that the string as argument (or a copy of the original string)
int pal(char *s) {
int n = strlen(s);
if (n <= 1) return 1;
if (s[0] != s[n-1]) return 0;
s[n-1] = '\0';
return pal(++s);
}
return 0: not a palindrome, 1: is a palindrome
Note the string is altered, so you can call it this way if it's a problem (or if the string is created in a static area)
char *copy = malloc(strlen(string)+1); // string is original string
strcpy(copy, string);
int ispal = pal( copy );
printf("Is %s a palindrome\n", ispal ? "":"not");

Reverse the order of an integer in C [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
I am currently learning C as part of a course and I have a task to reverse the order of a number without using any arithmetic (wording of the task).
I currently have this:
#include <stdio.h>
int main()
{
int n, reverse = 0;
printf("Enter a number to reverse\n");
scanf("%d", &n);
while (n != 0) {
reverse = reverse * 10;
reverse = reverse + n_10;
n = n / 10;
}
printf("Reverse of entered number is = %d\n", reverse);
return 0;
}
But this solution uses arithmetic. How can I alter this to complete the task?
From the exercise sheet, "though even at three
digits the naïve approach quickly grows unmanageable with arithmetic (try it!).
Your goal: Design 3-digit solution without using any arithmetic.(Hint: use scanf.)"
The wording of the question was confusing but to be clear the question is:
How do you reverse the order of a number, e.g. 123456789 to 987654321, without without using math. So the solution is to scanf to read the number and swap the numbers in a loop as the answer below.
You can just read it in as a string.
int main()
{
char str[80];
fgets(str, 80, stdin);
strrev(str);
printf("%s\n", str);
}
void strrev(char *str)
{
char *end, tmp;
end = str + strlen(str) - 1;
for (; end > str; --end, ++str) {
tmp = *end;
*end = *str;
*str = tmp;
}
}
I don't know if you consider pointer arithmetic to be "arithmetic"
Read as series of short strings that can hold 1 digit and then print in the reserve order.
char buf[10][2] = { 0 };
scanf("%1[0-9]%1[0-9]%1[0-9]%1[0-9]%1[0-9]%1[0-9]%1[0-9]%1[0-9]%1[0-9]%1[0-9]",
&buf[0], &buf[1], &buf[2], &buf[3], &buf[4],
&buf[5], &buf[6], &buf[7], &buf[8], &buf[9]);
printf("%s%s%s%s%s%s%s%s%s%s",
buf[9], buf[8], buf[7], buf[6], buf[5],
buf[4], buf[3], buf[2], buf[1], buf[0]);
Obviously limited to max 10 digits.
A recusive approach, inpsired by #Nisse Engström. Works for any reasonable length input.
void pr(void) {
char digit[2];
if (scanf("%1[0-9]",digit)) {
pr();
printf("%s",digit);
}
}
int main(void) {
pr();
return 0;
}
Input
012345678901234567890123456789
Output
987654321098765432109876543210
Of course if (scanf("%1[0-9]",digit)) { should be if (scanf("%1[0-9]",digit) == 1) { to cope with EOF but that then may be "arithmetic".
Using scanf():
int
scanf (){
int
stdin =
getchar ();
return
stdin <0||
stdin ==
'\n'?
stdin :(
scanf (),
putchar (
stdin )),
'\n';}
int
main (){
putchar (
scanf ()
);}
Read integer, use sprintf() function to convert it into string and then use the library function strrev() to reverse the string.

programming in C involving strings [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
1.actually I want to first give a number N (no. of strings I want to enter) as an input then in next line a string using gets().But when I press enter then the no. of strings I could enter is N-1.I tried using printf("\n") but it didn't work.Please anyone could help me in this.eg:
//code
int N,i,arr[N];
char str[50];
scanf("%d",&N) //no. of strings required
for(i=0;i<N;i++)
{
gets(str);
arr[i]=strlen(a);
}
for(i=0;i<N;i++)
{
printf("%d\n",arr[i]);
}
i want to enter my input to be like this:
2 //no. of strings
ABCFD //string 1
ASWD //string 2
//But actually what i am getting using printf("\n")
and output:
5
4
but what i am getting:
2
//blank space
ASWD //string 2
and output
0
4
After entering a value for N there remains a newline in the input buffer, which is accepted by the following gets as a blank input. In any case gets is a deprecated function: please use fgets such as like this. I've printed each entry to show there is a newline at the end of each, and removed that newline.
#include <stdio.h>
#include <string.h>
int main(void) {
int N, i;
char str[50];
printf("Enter number of cases\n");
scanf("%d%*c", &N); // read newline too, but discard
for(i=0; i<N; i++)
{
printf("\nEnter string\n");
if (fgets(str, sizeof str, stdin) == NULL)
return 1;
printf("Shows newline >>%s<<\n", str); // show that newline is retained
str [ strcspn(str, "\r\n") ] = 0; // remove trailing newline
printf("After removal >>%s<<\n", str); // show that newline was removed
}
return 0;
}
Program output
Enter number of cases
2
Enter string
one
Shows newline >>one
<<
After removal >>one<<
Enter string
two
Shows newline >>two
<<
After removal >>two<<
Try it --
int lineNumbers;
scanf("%d", &lineNumbers);
char **linesOfString = (char**) malloc(lineNumbers * sizeof(char *));
int i;
for(i = 0; i < lineNumbers; i++) {
fflush(stdin);
linesOfString[i] = (char *) malloc(255 * sizeof(char));
scanf("%s", linesOfString[i]);
}
for(i = 0; i < lineNumbers; i++) {
printf("%s", linesOfString[i]);
}
free(linesOfString);
return 0;
It sounds like you are not getting the number of strings expected, is this correct?
If this is the case, look at your looping code.
The most likely newbie mistake is with indexing. Arrays in C are 0 indexed.
This means that if you have int test[3], the indexes of test will be 0, 1, and 2. This means that the highest index WILL be N-1.
So, make sure that the first string you are accepting is being placed into index 0, and not index 1.

usage of scanf inside while test condition

I want to store a series of integers till i press an enter in an array.How can i implement that
Input:
1(tab space)2(tab space)3(tab space)4(tab space)enter
i tried doing this
#include<stdio.h>
main()
{
int i,j,c,d;
int a[5];
for(i=0;i<2;i++){
j=0;
while((d=scanf("%d",&c))==1){
a[j]=c;
j=j+1;
}
}
}
I dont know how scanf works and using scanf return value.Please explain how i can store this input if its not impossible to do so with scanf and also
2)What else can be used inside scanf along with %d ?
I have a file with 200 rows with numbers like this
(NOTE: each row has varied number of values but all numbers are less than 200)
1\t2\t3\t4\t5\t
2\t3\t4\t5\t6\t7\t8\t
11\t12\t13\t
.
.
200
... so i have to store this as an adjacency list representation
For the first part of your question. scanf() returns number of elements successfully read but it is of no use here and you can just scan in a loop and scanf() will pick your integers in a line when you press enter.
#include <stdio.h>
int main(void) {
int a[5];
int i, n;
for(i=0;i<5;i++)
{
if(scanf("%d",&a[i]) != 1)
{
printf("Value not read correctly\n");
break;
}
}
n = i;
for(i=0;i<n;i++)
printf("%d\n",a[i]);
return 0;
}
For the second question you have to do something line
1.Read a line from your file using fgets()
2.Break your line using strtok() with tab as delimiter.
3.Now convert each token to integer using atoi()
4.Now do whatever you want with the integer. i.e. create a node add your integer to the node
Let's make some reasonable assumptions about the width of each row.
These assumptions are useful for simple code, though not needed in general.
#define LINE_WIDTH_MAX 1000
#define INTS_PER_LINE_MAX 100
#define ROWS_PER_FILE (200 /* given by OP */)
Read each row with fgets(), then scan. Could use strtol(), sscanf() or various approaches.
This method uses sscanf() and "%n" to determine when the next number might follow.
int row;
for (row = 0; row < ROWS_PER_FILE; row++) {
char buf[LINE_WIDTH_MAX + 2];
if (fgets(buf, sizeof buf, stdin) == NULL) {
break; // Handle EOF or IO error
}
int num[INTS_PER_LINE_MAX];
char *p = buf;
for (int i = 0; i<INTS_PER_LINE_MAX; i++) {
int n = 0;
if (1 != sscanf(p, "%d %n", &num[i], &n)) {
break;
}
p += n;
}
if (*p) Handle_GarbageInLIne();
// do something with the `i` numbers
}
Notes:
Advise never use scanf()/

Resources