How do I extract the numbers from string in C? - c

following are the strings provided by the user to me -
"1 20";
"1 203";
"1 2030";
in above examples 1 is query and 20,203,2030 are the numbers to be extracted,how can I extract them in C language?

There are many ways to parse a string containing numbers. If you expect the string to have a fixed format with 2 integers, the simplest solution is to use sscanf():
#include <stdio.h>
int parse2numbers(const char *str) {
int a, b;
// sscanf returns the number of successful conversions
int n = sscanf(str, "%d%d", &a, &b);
if (n == 2) {
printf("success: a=%d, b=%d\n", a, b);
return 1;
}
if (n == 1) {
printf("failure: only one number provided: a=%d, str=%s\n", a, str);
return 0;
}
if (n == 0) {
printf("failure: invalid format: %s\n", str);
return 1;
}
printf("failure: encoding error: n=%d, str=%s\n", n, str);
return 0;
}
If the string can contain a variable number of integers, you could use strtol() to parse one integer at a time:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
void parse_numbers(const char *str) {
long a;
char *p;
for (;; str = p) {
errno = 0;
// strtol returns a long int
// updates `p` to point after the number in the source string
// sets errno in case of overflow and returns the closest long int
a = strtol(str, &p, 10);
if (p == str)
break;
if (errno != 0) {
printf("overflow detected: ");
}
printf("got %ld\n", a);
}
if (*str) {
printf("extra characters: |%s|\n", str);
}
}

I have not tested it but I think theoratically this should work
int rows=2, columns=4 // defining length of array
char ch[rows] [columns] = {"1 90"}, {"2 90"}; // creating two dimentional array for sample data
for (int i = 0; i < rows; i++) { // looping throw first dimention
// this only works if data is sorted and there is no missing indes in between like [1 200] [3 200] will not work but [1 200] [2 200] should
char* index;
if ( ch[i] [0] != itoa(i+1, index, 10) ) // checking if index donot match the row then skip this itteration and move to next one.
continue;
for ( int j = i+2; j<columns; j++) { // looping through second dimention
printf("%c\n", ch[i][j]); // printing that second dimention
}
}

Related

Comparing digits of two inputs to see if they are the same

I am currently trying to finish a code where a user inputs two 5 digit long numbers. The code then checks to see if there are any identical numbers in the same spot for the two numbers and displays how many identical numbers there are in the same spot of the two inputs. (ex. comparing 56789 and 94712 there would be one similar digit, the 7 in the 3rd digit place.) As of now I have been able to break down the inputs into the digits in each spot, I just need help comparing them. Originally I thought I could just create an int that would serve as a counter and use modulus or division to output a 1 whenever the digits were the same, but I have been unable to put together a formula that outputs a 1 or 0 depending on if the digits are alike or not.
suppose you know the length of strings n (as a condition you would need them to be equal, if they differ in length other validation is needed)
//n is the length of string
for(int i=0;i<n;i++)
{
if(string1[i]==string2[i])
{
//do something, make a counter that increments here...
//also save index i, so you can tell the position when a match occured
}else
{
//do something else if you need to do something when chars didnt match
}
}
Here you when i=0, you are comparing string1[0] with string2[0], when i=1, you compare string1[1] with string2[1] and so on.....
I'd recommend reading the two in as strings or converting to strings if you have the ability to. From there it's a simple string compare with a counter. Something like this:
#include <stdio.h>
#include <ctype.h>
#include <string.h>
int is_numeric(char *str)
{
while (*str)
if (!isdigit(*str++))
return (0);
return (1);
}
int main(void)
{
char num1[32];
char num2[32];
int count = 0;
printf("Digit 1\n>> ");
if (scanf("%5s", num1) != 1 || !is_numeric(num1))
return (0);
printf("Digit 2\n>> ");
if (scanf("%5s", num2) != 1 || !is_numeric(num2))
return (0);
if (strlen(num1) != 5 || strlen(num2) != 5)
return (0);
for (int i=0; i<5; ++i)
if (num1[i] == num2[i])
++count;
printf("%d\n", count);
return (0);
}
You can do it very easy using modulo (%) and divide (/). First you do % 10 to get the least significant digit and do the compare. Then you do / 10 to remove the least significant digit. Like:
#include <stdio.h>
#include <string.h>
int main(void) {
unsigned int i1, i2;
int i;
int cnt = 0;
printf("Input first 5 digit number:\n");
if (scanf(" %u", &i1) != 1 || i1 < 10000 || i1 > 99999) // Get integer input and check the range
{
printf("input error\n");
return 0;
}
printf("Input second 5 digit number:\n");
if (scanf(" %u", &i2) != 1 || i2 < 10000 || i2 > 99999) // Get integer input and check the range
{
printf("input error\n");
return 0;
}
for (i=0; i<5; ++i)
{
if ((i1 % 10) == (i2 % 10)) ++cnt; // Compare the digits
i1 = i1 / 10;
i2 = i2 / 10;
}
printf("Matching digits %d\n", cnt); // Print the result
return 0;
}
It can also be done using strings. Read the input as unsigned int and then convert the value to a string using snprintf and finally compare the two strings character by character.
Something like:
#include <stdio.h>
#include <string.h>
int main(void) {
char str1[32];
char str2[32];
unsigned int i1, i2;
int i;
int cnt = 0;
printf("Input first 5 digit number:\n");
if (scanf(" %u", &i1) != 1) // Get integer input
{
printf("input error\n");
return 0;
}
snprintf(str1, 32, "%u", i1);
if (strlen(str1) != 5) // Convert to string
{
printf("input error - not 5 digits\n");
return 0;
}
printf("Input second 5 digit number:\n");
if (scanf(" %u", &i2) != 1) // Get integer input
{
printf("input error\n");
return 0;
}
snprintf(str2, 32, "%u", i2); // Convert to string
if (strlen(str2) != 5)
{
printf("input error - not 5 digits\n");
return 0;
}
for (i=0; i<5; ++i)
{
if (str1[i] == str2[i]) ++cnt; // Compare the characters
}
printf("Matching digits %d\n", cnt); // Print the result
return 0;
}
The reason for taking the input into a unsigned int instead of directly to a string is that by doing that I don't have to check that the string are actually valid numbers (e.g. the user type 12W34). scanf did that for me.

Reading integers with commas between them

I assumed using strtok would be best because of the formatting of the input.
But I've run into a few problems when trying to detect errors:
an example of a line the program would read:
.data 123,456,89
.data 12, 34, 53 , 64
these are all ok.
My problem is when the input is incorrect, for example:
.data 200 4000 // no comma speration
.data 1, ,3 // ,3 should be an error
.data 4, // the extra , should be an error
.data 12.2 // the .2 should be an error
and so on
My code (SIZE is for buffer size = 30, valid_num goes through the token to see if all the chars are numbers), the idea was to first check the validity of the tokens and add them to a buffer, if all numbers are valid, add the numbers to my data base:
while((sptr = strtok(NULL, ", \t\n")) != NULL){ //this is after reading using strtok before.
if(i < SIZE && valid_num(sptr)){ //buffer is not full and the token contains only numbers
temp_num = atoi(sptr);
if(temp_num >= MIN_VAL && temp_num <= MAX_VAL){ //number is within the required size
buffer[i] = temp_num; /*fill buffer*/
i++;
}
else{
fprintf(stderr, "(%d) Error: %d is out of bounds. Valid numbers are between %d and %d\n", line_count, temp_num, MIN_VAL, MAX_VAL);
}
}
else{
fprintf(stderr, "(%d) Error: %s is not a valid number\n",line_count, sptr);
}
tok_count++;
}
if(i == tok_count){ //if all tokens were read correctly, add the data to database.
DC += add_data(buffer, tok_count, DC, data_Table);
}
else{
if(sptr != NULL){
fprintf(stderr, "(%d) Error: %s is not a digit, .data can only be used for integers\n", line_count, sptr);
}
}
Should I try to do the same but with sscanf, even though the length of the input is unknown?
How can I enforce a certain pattern? number - comma - number ...
Perhaps using a few different strtok inside the loop?
There are many ways to parse the line.
OP's temp_num = atoi(sptr); does not detect overflow as 1) overflow with atoi() is undefined and 2) there is no error return value.
I believe the below will cope with all hostile input. It does not use strtok(), but strtol() to find non-numeric input.
Making use of helper functions provides clarity of each step.
#include <ctype.h>
#include <errno.h>
#include <stdlib.h>
void consume_whitespace(char **input) {
while (isspace((unsigned char ) **input))
(*input)++;
}
int parse_int(char **input, int *dest) {
char *endptr;
errno = 0;
long y = strtol(*input, &endptr, 10);
if (*input == endptr) return -1; // no conversion
if (errno) return -1; // overflow
#if LONG_MIN < INT_MIN || LONG_MAX > INT_MAX
if (y < INT_MIN || y > INT_MAX) return -1; // overflow
#endif
*input = endptr;
*dest = (int) y;
return 0;
}
int parse_data_line(char *input, const char *prefix, int *dest, int n) {
size_t prefix_length = strlen(prefix);
if (memcmp(input, prefix, prefix_length)) return -1;
input += prefix_length;
int i;
for (i = 0; i < n; i++) {
consume_whitespace(&input);
if (*input == '\0') break;
if (i > 0 && *input++ != ',') return -1;
if (parse_int(&input, &dest[i])) return -1;
}
consume_whitespace(&input);
if (*input) return -1; // extra text
return i;
}
Example usage
#define SIZE 30
int main() {
int numbers[SIZE];
char *input = foo();
int count = parse_data_line(input, ".data", numbers, SIZE);
if (count < 0) puts("Fail");
else bar(numbers, count);
}

Input to array of strings won't show?

I'm in C and I'm supposed to have an input of numbers (don't know how many) formatted into one column without storing them into an array of integers. I can't figure out why my code won't read the input and out put it. Please help.
#include <stdio.h>
#include <stdlib.h>
int main() {
int i;
char *nums[400];
for (i=0; i<nums; i++) {
scanf(nums[i]);
printf( "%.*s", 3, nums[i] );
}
return 0;
}
You have an array of 400 pointers, but you've never initialized them. Instead, you could declare a 2-dimension array:
char nums[400][4];
Then you're trying to use nums as a limit to the for loop. What you actually want is the number of elements in nums, which is sizeof(nums)/sizeof(nums[0]); or you could define a macro that specifies the size of the array.
Next, you left out the format string argument to scanf().
#include <stdio.h>
#include <stdlib.h>
#declare SIZE 400
int main()
{
int i;
char *nums[SIZE][4];
for(i=0; i<SIZE; i++){
scanf("%3s", nums[i]);
printf( "%.*s", 3, nums[i] );
}
return 0;
}
As Baramar correctly and thoroughly explained your main problems, I think I might have a different understanding of your problem. You want a given string of number, e.g.: 2134567896543245678 and print it out in a single column, neatly formated in rows of three digits each like that:
213
456
789
654
324
567
8
without an intermittent array of integers.
That could be done like e.g.: this
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFFER_SIZE 512
int main()
{
int res;
// for the scanf input, set all to '\0'
char buffer[BUFFER_SIZE + 1] = { '\0' }, *idx;
size_t len, i;
// restrict max-size to BUFFER_SIZE
res = scanf("%512s", buffer);
if (res != 1) {
exit(EXIT_FAILURE);
} else {
if (strcmp(buffer, "exit") == 0) {
exit(EXIT_SUCCESS);
}
// TODO: check if the buffer contains all digits
len = strlen(buffer);
idx = buffer;
for (i = len; i >= 3; i -= 3, idx += 3) {
printf("%.3s\n", idx);
}
// last entries, if any
if (*idx != '\0') {
printf("%s\n", idx);
}
}
exit(EXIT_SUCCESS);
}
If you get actual integers in a row like e.g.: 12 3123 23478 34 5456 567456 567 678 you can use something like that:
EDIT
After the comment by the OP to use floating points I changed the code to accept input of the form:
24722.319352 51433.662233
56087.991042 49357.684934 67875.375848 68421.563197
54521.615295
22744.470483
38097.001461 80878.250982
92131.575748 7217.137271
20750.671365 7620.695008 37118.391541 28655.609469 46885.110202 87114.202312
46462.577299
20557.716648
And the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXNUM 400
int main()
{
int res;
int i = 0, m;
// input and two temporary variables
double in, in1, in2;
for (m = 0; m < MAXNUM; m++) {
res = scanf("%lf", &in);
if (res != 1) {
break;
} else {
switch (i) {
case 0:
// set value of first temporary variable to input
in1 = in;
// increment indicator indicating position in output row
i++;
break;
case 1:
in2 = in;
i++;
break;
case 2:
// print the three numbers and a newline
fprintf(stdout, "%f %f %f\n", in1, in2, in);
// reset counter
i = 0;
break;
}
}
}
// if there are still numbers, print them
if (i != 0) {
if (i == 1) {
fprintf(stdout, "%f\n", in1);
} else {
fprintf(stdout, "%f %f\n", in1, in2);
}
}
exit(EXIT_SUCCESS);
}
Try it out with
$ gcc-4.9 -O3 -g3 -W -Wall -Wextra -std=c11 sc.c -o sc
$ ./sc < floatin
24722.319352 51433.662233 56087.991042
49357.684934 67875.375848 68421.563197
54521.615295 22744.470483 38097.001461
80878.250982 92131.575748 7217.137271
20750.671365 7620.695008 37118.391541
28655.609469 46885.110202 87114.202312
46462.577299 20557.716648
If you enter less than 400 entries you need to end with EOF which can be triggered in most Unix shells with ctrl+d or set an entry to end the entries like e.g.: -1 if all you have is positive numbers and check for it to break out of the loop. If you submit a file like in the example above it works automatically.

How to test input is sane

Consider the following simple C program.
//C test
#include<stdio.h>
int main()
{
int a, b, c;
printf("Enter two numbers to add\n");
scanf("%d%d",&a,&b);
c = a + b;
printf("Sum of entered numbers = %d\n",c);
return 0;
}
How do you check the values entered are actually two integers in some sensible range? Currently, if you just enter "a" and then return you get the output "Sum of entered numbers = 32767".
Examples of incorrect input I would like to prevent.
2 3 4 (wrong number of numbers)
apple (not a number)
11111111111111111111111111 1111111111111111111111111111111111111 (numbers out of range)
Or should I be using fgets and sscanf or even strtol ?
User input is evil. Parse per:
(optional whitespace)[decimal int][whitespace][decimal int](optional whitespace)
strtol() and family have better error handling than scanf().
Coda: Best to handle user input in a helper function. Break into 2 parts: I/O and parsing.
#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
// return 1 (success), -1 (EOF/IOError) or 0 (conversion failure)
int Readint(const char *prompt, int *dest, size_t n) {
char buf[n * 21 * 2]; // big enough for `n` 64-bit int and then 2x
fputs(prompt, stdout); // do not use printf here to avoid UB
fflush(stdout); // per #OP suggestion
if (fgets(buf, sizeof buf, stdin) == NULL) {
return -1;
}
const char *p = buf;
while (n-- > 0) {
char *endptr;
errno = 0;
long l = strtol(p, &endptr, 10);
if (errno || (p == endptr) || (l < INT_MIN) || (l > INT_MAX)) {
return 0;
}
*dest++ = (int) l;
p = endptr;
}
// Trailing whitespace OK
while (isspace((unsigned char) *p)) p++;
// Still more text
if (*p) return 0;
return 1;
}
int main() { // for testing
int Result;
do {
int dest[2] = { -1 };
Result = Readint("Enter two numbers to add\n", dest, 2);
printf("%d %d %d\n", Result, dest[0], dest[1]);
} while (Result >= 0);
return 0;
}
You can use like:
if( scanf("%d%d",&a,&b) == 2)
{
//two integer values has been read successfully
//do your stuff here
}
else
{
//Wrong input
}
Also you can do this to prevent anything after second number
int a,b;
char c;
if( scanf("%d%d%c", &a, &b, &c) == 3) {
if (c == '\n') {
puts("good");
}
} else {
puts("bad");
}
return 0;
}
You can use the following macro
#define SCAN_ONEENTRY_WITHCHECK(FORM,X,COND) \
do {\
char tmp;\
while(((scanf(" "FORM"%c",X,&tmp)!=2 || !isspace(tmp)) && !scanf("%*[^\n]"))\
|| !(COND)) {\
printf("Invalid input, please enter again: ");\
}\
} while(0)
and you call it in this way in the main
int main()
{
int a, b, c;
printf("Input first integer, valid choice between 0 and 10: ");
SCAN_ONEENTRY_WITHCHECK("%d",&a,(a>=0 && a<=10));
printf("Input second integer, valid choice between 0 and 10: ");
SCAN_ONEENTRY_WITHCHECK("%d",&b,(b>=0 && b<=10));
c = a + b;
printf("Sum of entered numbers = %d\n",c);
return 0;
}
for more detail concerning this macro please refer to: Common macro to read input data and check its validity
A simple way would be,
int a=0, b=0, c=0;
initialise them to 0
Additionally, the check suggested by Midhun is good to check if there are two inputs.
you can test this one.
#include <stdio.h>
int main(void)
{
int a, b, c;
printf("Enter two numbers to add\n");
scanf("%d%d",&a,&b);
if(scanf("%d%d",&a,&b) == 2)
{
c = a + b;
printf("Sum of entered numbers = %d\n",c);
}
return 0;
}

How to extract numbers from string in c?

Say I have a string like ab234cid*(s349*(20kd and I want to extract all the numbers 234, 349, 20, what should I do ?
You can do it with strtol, like this:
char *str = "ab234cid*(s349*(20kd", *p = str;
while (*p) { // While there are more characters to process...
if ( isdigit(*p) || ( (*p=='-'||*p=='+') && isdigit(*(p+1)) )) {
// Found a number
long val = strtol(p, &p, 10); // Read number
printf("%ld\n", val); // and print it.
} else {
// Otherwise, move on to the next character.
p++;
}
}
Link to ideone.
A possible solution using sscanf() and scan sets:
const char* s = "ab234cid*(s349*(20kd";
int i1, i2, i3;
if (3 == sscanf(s,
"%*[^0123456789]%d%*[^0123456789]%d%*[^0123456789]%d",
&i1,
&i2,
&i3))
{
printf("%d %d %d\n", i1, i2, i3);
}
where %*[^0123456789] means ignore input until a digit is found. See demo at http://ideone.com/2hB4UW .
Or, if the number of numbers is unknown you can use %n specifier to record the last position read in the buffer:
const char* s = "ab234cid*(s349*(20kd";
int total_n = 0;
int n;
int i;
while (1 == sscanf(s + total_n, "%*[^0123456789]%d%n", &i, &n))
{
total_n += n;
printf("%d\n", i);
}
here after a simple solution using sscanf:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
char str[256]="ab234cid*(s349*(20kd";
char tmp[256];
int main()
{
int x;
tmp[0]='\0';
while (sscanf(str,"%[^0123456789]%s",tmp,str)>1||sscanf(str,"%d%s",&x,str))
{
if (tmp[0]=='\0')
{
printf("%d\r\n",x);
}
tmp[0]='\0';
}
}
Make a state machine that operates on one basic principle: is the current character a number.
When transitioning from non-digit to digit, you initialize your current_number := number.
when transitioning from digit to digit, you "shift" the new digit in:
current_number := current_number * 10 + number;
when transitioning from digit to non-digit, you output the current_number
when from non-digit to non-digit, you do nothing.
Optimizations are possible.
If the numbers are seprated by whitespace in the string then you can use sscanf(). Since, it's not the case with your example,
you have to do it yourself:
char tmp[256];
for(i=0;str[i];i++)
{
j=0;
while(str[i]>='0' && str[i]<='9')
{
tmp[j]=str[i];
i++;
j++;
}
tmp[j]=0;
printf("%ld", strtol(tmp, &tmp, 10));
// Or store in an integer array
}
#include<stdio.h>
#include<ctype.h>
#include<stdlib.h>
void main(int argc,char *argv[])
{
char *str ="ab234cid*(s349*(20kd", *ptr = str;
while (*ptr) { // While there are more characters to process...
if ( isdigit(*ptr) ) {
// Found a number
int val = (int)strtol(ptr,&ptr, 10); // Read number
printf("%d\n", val); // and print it.
} else {
// Otherwise, move on to the next character.
ptr++;
}
}
}
Or you can make a simple function like this:
// Provided 'c' is only a numeric character
int parseInt (char c) {
return c - '0';
}

Resources