Ok so I need to input a string like this
IP_1/MASK IP_2 NUM [NET_1 NET_2 NET3 ... NET_NUM]
for example :
192.168.25.87/24 192.168.26.1 3 192.168.0.0/16 192.0.26.0/16 192.168.26.0/24
And then to split this string into multiple variables ( IP_1, MASK etc).
I followed on internet a guide how to split it and I did it like this:
int main()
{
char* IP_1[256],IP_2[256],NET[256][256],character[256];
int MASCA,NUM,i=1,j;
char *p;
gets(character);
p=strtok(character,"/ ");
while(p!=NULL)
{
printf("%s\n",p);
p=strtok(NULL,"/ ");
}
So, doing this I split the array into multiple elements, but how can I save these elements into IP_1, MASK IP_2, NUM NET_1 etc ... ?
There are many way.
For example, do as follows.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void){
char IP_1[256], IP_2[256], NET[256][256], line[256], rest[256];
int MASK, NUM, i;
char *p;
fgets(line, sizeof line, stdin);//gets has already been abolished.
//Since the first three elements are fixed, use sscanf
if(3 > sscanf(line, "%s %s %d %255[^\n]%*c", IP_1, IP_2, &NUM, rest)){
printf("invalid input\n");
return -1;
}
if(NULL==(p = strchr(IP_1, '/'))){
printf("invalid input\n");
return -1;
}
*p = 0;// Replace '/' with '\0'
MASK = atoi(p + 1);// convert next '/' to int
for(p=strtok(rest, " \n"), i = 0; i < NUM && p; ++i, p=strtok(NULL, " \n")){
strcpy(NET[i], p);//strtok and copy
}
//test print
printf("IP_1:%s\n", IP_1);
printf("MASK:%d\n", MASK);
printf("IP_2:%s\n", IP_2);
for(i = 0; i < NUM; ++i)
printf("NET_%d:%s\n", i + 1, NET[i]);
}
Related
I am currently trying to parse UnicodeData.txt with this format: ftp://ftp.unicode.org/Public/3.0-Update/UnicodeData-3.0.0.html However, I am hitting a problem in that when I try to read, say a line like the following.
something;123D;;LINE TABULATION;
I try to get the data from the fields by code such as the following. The problem is that fields[3] is not getting filled in, and scanf is returning 2. in is the current line.
char fields[4][256];
sscanf(in, "%[^;];%[^;];%[^;];%[^;];%[^;];",
fields[0], fields[1], fields[2], fields[3]);
I know this is the correct implementation of scanf(), but is there a way to get this to work, short of making my own scanf()?
scanf does not handle "empty" fields. So you will have to parse it on your own.
The following solution is:
fast, as it uses strchr rather than the quite slow sscanf
flexible, as it will detect an arbitrary number of fields, up to a given maximum.
The function parse extracts fields from the input str, separated by semi-colons. Four semi-colons give five fields, some or all of which can be blank. No provision is made for escaping the semi-colons.
#include <stdio.h>
#include <string.h>
static int parse(char *str, char *out[], int max_num) {
int num = 0;
out[num++] = str;
while (num < max_num && str && (str = strchr(str, ';'))) {
*str = 0; // nul-terminate previous field
out[num++] = ++str; // save start of next field
}
return num;
}
int main(void) {
char test[] = "something;123D;;LINE TABULATION;";
char *field[99];
int num = parse(test, field, 99);
int i;
for (i = 0; i < num; i++)
printf("[%s]", field[i]);
printf("\n");
return 0;
}
The output of this test program is:
[something][123D][][LINE TABULATION][]
Update: A slightly shorter version, which doesn't require an extra array to store the start of each substring, is:
#include <stdio.h>
#include <string.h>
static int replaceSemicolonsWithNuls(char *p) {
int num = 0;
while ((p = strchr(p, ';'))) {
*p++ = 0;
num++;
}
return num;
}
int main(void) {
char test[] = "something;123D;;LINE TABULATION;";
int num = replaceSemicolonsWithNuls(test);
int i;
char *p = test;
for (i = 0; i < num; i++, p += strlen(p) + 1)
printf("[%s]", p);
printf("\n");
return 0;
}
Just in case you would like to consider this following alternative, using scanfs and "%n" format-specifier, used for reading in how many characters have been read by far, into an integer:
#include <stdio.h>
#define N 4
int main( ){
char * str = "something;123D;;LINE TABULATION;";
char * wanderer = str;
char fields[N][256] = { 0 };
int n;
for ( int i = 0; i < N; i++ ) {
n = 0;
printf( "%d ", sscanf( wanderer, "%255[^;]%n", fields[i], &n ) );
wanderer += n + 1;
}
putchar( 10 );
for ( int i = 0; i < N; i++ )
printf( "%d: %s\n", i, fields[i] );
getchar( );
return 0;
}
On every cycle, it reads maximum of 255 characters into the corresponding fields[i], until it encounters a delimiter semicolon ;. After reading them, it reads in how many characters it had read, into the n, which had been zeroed (oh my...) beforehand.
It increases the pointer that points to the string by the amount of characters read, plus one for the delimiter semicolon.
printf for the return value of sscanf, and the printing of the result is just for demonstration purposes. You can see the code working on http://codepad.org/kae8smPF without the getchar(); and with for declaration moved outside for C90 compliance.
I don't think sscanf will do what you need: sscanf format %[^;] will match a non-empty sequence of not-semicolon characters. The alternative would be using readline with the separator being ';', like:
#include <iostream>
#include <sstream>
#include <string>
int main() {
using namespace std;
istringstream i { "something;123D;;LINE TABULATION;\nsomething;123D;;LINE TABULATION;\nsomething;123D;;LINE TABULATION;\n" };
string a, b, c, d, newline;
while( getline(i, a, ';') && getline(i, b, ';') && getline(i, c, ';') && getline (i, d, ';') && getline(i, newline) )
cout << d << ',' << c << '-' << b << ':' << a << endl;
}
(I have only seen you took the c++ tag off this question now, if your problem is c-only, I have another solution, below:)
#include <string.h>
#include <stdio.h>
int main() {
typedef char buffer[2048];
buffer line;
while( fgets(line, sizeof(line), stdin) > 0 ) {
printf("(%s)\n", line);
char *end = line;
char *s1 = *end == ';' ? (*end = '\0'), end++ : strtok_r(end, ";", &end);
char *s2 = *end == ';' ? (*end = '\0'), end++ : strtok_r(end, ";", &end);
char *s3 = *end == ';' ? (*end = '\0'), end++ : strtok_r(end, ";", &end);
char *s4 = *end == ';' ? (*end = '\0'), end++ : strtok_r(end, ";", &end);
printf("[%s][%s][%s][%s]\n", s4, s3, s2, s1);
}
}
I need code that can count the words from a string without counting multiple spaces between them.
I could code a program that counts the words with only 1 empty space between them, but I don't know how I should code it when it would be more than 1 empty space. I thought something like a for loop that checks if the char before it is a space, but I don't know how to do that. And I want to mention that I'm a beginner in C.
#include <stdio.h>
#include <string.h>
int main()
{
char s[200];
int count = 0, i;
printf("enter the string: ");
fgets(s,200,stdin);
for (i = 0;s[i] != '\0';i++)
{
if (s[i] == ' ')
count++;
}
printf("number of words in given string are: %d\n", count+ 1);
return(0);
}
You can introduce a flag to tell whether the previous character was a space. Something like:
#include <stdio.h>
#include <string.h>
int main()
{
char s[200];
int count = 0, i;
int last_was_space = 1;
printf("enter the string: ");
fgets(s,200,stdin);
for (i = 0;s[i] != '\0';i++)
{
if (s[i] == ' ')
{
if (!last_was_space)
{
count++; // Only count when last char wasn't a space
last_was_space = 1;
}
}
else
{
// Update flag (unless this char is a newline)
if (s[i] != '\n') last_was_space = 0;
}
}
if (!last_was_space) ++count; // Count the last word if there wasn't a space before
printf("number of words in given string are: %d\n", count);
return(0);
}
Framing the problem in general terms helps here. Don't think of it as "counting words", or "counting spaces". Think of it as counting "transitions from separator to non-separator". Defining our terms:
Separator: start of string, or a single ASCII space
Non-separator: everything else
Examples (^ is start of string, _ is a literal space, $ is end of string):
^a_quick_brown_fox_jumps$
^ ^ ^ ^ ^ 5 transitions
^_a__quick___brownfox_jumps___$
^ ^ ^ ^ 4 transitions
^$
0 transitions
^___$
0 transitions
^__x$
^ 1 transition
Now in psuedo code:
def is_separator(char x):
return (x == NULL or x == ' ')
def is_non_separator(char x):
return (! is_separator(x))
let count = 0, last_char = NULL
while current_char = read_char():
if (is_non_separator(current_char) and is_separator(last_char)):
count++
From here, you can translate into specific languages or change the meaning of separators without affecting the logic of counting.
A bit more universal
size_t wcount(const char *s, const char *del, int countempty)
{
char *token;
size_t count = 0;
char *str = strdup(s);
if(str)
{
token = strtok(str, del);
while( token != NULL )
{
if(!strlen(token))
{
if(countempty)
{
count++;
}
}
else
{
count++;
}
token = strtok(NULL, del);
}
}
free(str);
return count;
}
int main ()
{
char str[] = "something to count ,., , . !! Stack overflow ";
printf("With empty %zu, Without empty%zu\n", wcount(str," ", 1), wcount(str," .,", 0));
}
count the words from a string without counting multiple spaces between them
Set a flag to determine if the beginning of a word is possible. Fewer special cases than looking for the end of the word.
Typically the requirement for "spaces" implies any white-space, then the task is easily coded:
#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
int main(void) {
char s[200];
printf("enter the string: ");
fgets(s, sizeof s, stdin);
int count = 0;
bool beginning_of_word_possible = true;
for (const char *p = s; *p; p++) {
if (isspace((unsigned char ) *p)) {
beginning_of_word_possible = true;
} else {
if (beginning_of_word_possible) {
count++;
}
beginning_of_word_possible = false;
}
}
printf("number of words in given string are: %d\n", count);
return (0);
}
#P__J__ offered a good idea that passes in a list of delimiters. Below is a similar and short solution that does not allocate memory nor change the supplied string.
#include <string.h>
size_t word_count(const char *s, const char *delimiters) {
size_t count = 0;
while (*(s += strspn(s, delimiters))) { // Advance s by the matching delimiters.
count++;
s += strcspn(s, delimiters); // Advance s by the non-matching delimiters.
}
return count;
}
Test
int main(void) {
const char *de = " \n";
printf("%zu\n", word_count("", de));
printf("%zu\n", word_count("\n", de));
printf("%zu\n", word_count(" ", de));
printf("%zu\n", word_count("abc", de));
printf("%zu\n", word_count(" abc", de));
printf("%zu\n", word_count(" abc \n", de));
printf("%zu\n", word_count("abc xyz", de));
printf("%zu\n", word_count(" abc xyz", de));
printf("%zu\n", word_count(" abc xyz \n", de));
}
Output
0
0
0
1
1
1
2
2
2
Short and Simple Version:
#include <stdio.h>
int main(void) {
char str[] = " Hello, This is a test of a word counter";
int i = 0;
for(char* s=str; strtok(s," "); i++) s = NULL;
printf("number of words in given string are: %d\n", i);
return 0;
}
Output
Success #stdin #stdout 0s 9424KB
number of words in given string are: 9
I have a string, like "101 1 13" and I need to split it to a int aux[3] --> resulting in aux[0] = 101, aux[1] = 1 and aux[2] = 13 (in this case). How can
I do that?
In the example of the code below I get op as a String and want to get the value of the INTs in there. Each int is divided in the string by a white space(" ").
Another detail: I need the code to compile with flag -std=c99, so the answer that was accepted would not work.
#include <stdio.h>
#include <stdlib.h>
//example of str = "101 1 14" (char *)
// example of output = {101, 1, 14}(int *)
int* stoi(char *str) {
// function to split str into 3 ints
}
int main() {
char op[10];
int num[3];
scanf("%s\n", op);
num = stoi(op);
printf("%d %d %d", num[0], num[1], num[2]);
return 0;
}
First you need to tokenize your input (break apart the input into distinct elements). Then you need to parse/integerize the individual tokens by converting them from strings to the desired format.
Sample Code
#include <stdio.h>
#include <string.h>
#define BUF_LEN (64)
int main(void)
{
char buf[BUF_LEN] = { 0 };
char* rest = buf;
char* token;
int i = 0;
int iArr[100] = { 0 };
if ( fgets(buf, BUF_LEN, stdin) != NULL )
{
strtok(buf, "\n"); // Remove newline from input buffer in case we want to call fgets() again.
while ( (token = strtok_r(rest, " ", &rest)) != NULL )
{
iArr[i] = strtol(token, NULL, 10);
printf("Token %d:[%d].\n", i, iArr[i]);
i++;
}
}
return 0;
}
Sample Run
1231 12312 312 1232 1312
Token 0:[1231].
Token 1:[12312].
Token 2:[312].
Token 3:[1232].
Token 4:[1312].
Try to replace your code by following code.
The new code works only if input contains only single space between integers.
Your code:
while(op[cont] != '\0') {
for(i = 0; op[cont] != ' '; i++, cont++) {
num[i] += op[cont];
}
printf("num[i] = %d\n", num[i]);
}
New code:
while(op[cont] != '\0')
{
if(op[cont] != ' ')
num[i] = num[i]*10 + (op[cont]- '0');
else
i++;
cont++;
}
See this example of how to do that:
char string [10] = "101 1 666"
int v [3], n=0, j=0;
int tam = strlen(string);
int current_Len = 0;
for(i=0; i<tam; i++){
//32 = ascii for White space
if(string[i] != 32){
n = n*10 + string[i] - '0';
current_len++;
} else if (current_len > 0){
v[j++] = n;
current_len = 0;
n=0;
}
}
if (current_len > 0){
v[j++] = n;
}
This answer is assuming you know how much integers your string contain at the time of writing your code. It also uses specific clang/gcc extension (typeof) and may not be portable. But it may be helpful to someone (I mainly wrote it because I had nothing good to do).
#include <stdio.h>
#include <string.h>
struct {int _[3];} strToInt3(const char (*pStr)[])
{
int result[3] = {0}, *pr = result;
for(register const char *p = *pStr; *p; ++p)
{
if(*p == ' ') ++pr;
else
*pr *= 10,
*pr += *p - '0';
}
return *(__typeof__(strToInt3(0)) *)result;
}
int main()
{
char op[10];
int num[3];
scanf("%10[^\n]", op),
//memcpy(num, strToInt3(op)._, sizeof(num));
//or
*(__typeof__(strToInt3(0)) *)num = strToInt3(op);
printf("%d %d %d", num[0], num[1], num[2]);
}
I've commented the copying of returned array using memcpy and added a structure assignment. Although both must be valid (not standard I guess but working in most cases) I prefer the second option (and maybe some compiler optimizers will).
Also I assume ASCII character set for chars.
I found an easier approach to the problem. I insert a scanf, that don't catch the space blanket and convert it using atoi. As it is just 3 ints it doesn't become so bad to use this simple, repetitive way of catching the values. And it work with the -std=c99 flag, that I needed to use.
scanf("%s[^ ]\n", op);
num[0] = atoi(op);
scanf("%s[^ ]\n", op);
num[1] = atoi(op);
scanf("%s[^ ]\n", op);
num[2] = atoi(op);
printf("%d\n", num[0]);
printf("%d\n", num[1]);
printf("%d\n", num[2]);
It's quite bothering when reading unknown number of integers within a pair of parenthesis.
For example:
(1, 2, 3)
But We don't how many integers there are.
Rather than reading them entirely as a string, can anyone have any other ideas to fix that?
Many thanks.
It is terribly unclear what you really want from the posted question. But if you're talking about variable length arguments to a function, then:
Look into Variable arguments in C.
If you are talking about reading unknown no. of integers from input buffer, then you'll have to make your own function to read character by character, parsing the input for numbers, parenthesis and commas: A basic parser to do that is below(note, its not tested and can contain bugs) - understand and modify it accordingly. You can read in any no. of integers with this program.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
typedef enum { START, OPAREN, CPAREN, COMMA, DIGIT, EOF_S,UNKNOWN }Token;
int c;
unsigned char state = 0;
int numbers[100];
Token getToken(FILE *f)
{
while(isspace(c = fgetc(f)));
if(c == EOF) return EOF_S;
if(c == '(') return OPAREN;
if(c == ',') return COMMA;
if(c == ')') return CPAREN;
if(isdigit(c)) return DIGIT;
return UNKNOWN;
}
int getNumber(FILE *f)
{
int returnNumber = 0;
Token tok = START;
while(tok != DIGIT){
tok = getToken(f);
if(tok == UNKNOWN){ state = 1; return 0x0FFFFFFF;}
if(tok == EOF_S) { state = 2; return 0x0FFFFFFF;}
}
if(tok == DIGIT){
while(tok == DIGIT){
returnNumber = returnNumber * 10 + (c - '0');
tok =getToken(f);
}
}
return returnNumber;
}
int getNumbers(FILE *f, int *numbers_0)
{
int number;
int no_counter = 0;
while(((number = getNumber(f)) != 0x0FFFFFFF) && (state == 0)){
numbers_0[no_counter++] = number;
}
return no_counter; //returns no. of numbers between ( and ), separated by ','
}
int main(int argc, char *argv[])
{
int no, i;
no = getNumbers(stdin,numbers);
if(no > 100) no = 100;
for(i = 0; i < no; i++){
printf("%d\n",numbers[i]);
}
return 0;
}
Here after a simple C code to do it
#include <stdio.h>
int main(int argc, char **argv)
{
int x; char c='\0';
scanf("%*[(]");
while (c != ')' && scanf("%d %c", &x, &c)==2){
if (c!=',' && c != ')') {
printf ("format error in the input\n");
break;
}
printf("Number: %d\n", x);
}
}
If your input stream is stdin then use scanf as indicated in the above code
If your input stream is a file then use fscanf
if u need only read ( and processing right now) u can
read char C until C=='('
read char C if it space/tab/CR/LF continue step 2 else step 3
if C==')' End of reading list
so if u here c is a digit so u can getback char( use ungetc(C,stdin) ) and reread all number as integer .here u can opirate with intger as u wish. continue to 2.
If list is syntax correct above algo enogh else add where read C test on EOF and on step 4 test on alpha.
I think u can rewrite algo using C without goto.
I hope you are looking for a function implementation with variable arguments, below snippet will help you.
int add(int *total, int count, ...)
{
int i = 0;
va_list numbers;
va_start(numbers, count);
for (i = 0; i < count; i++)
{
*total += va_arg(numbers, int);
}
va_end(numbers);
}
You can call this function like
...
int result = 0;
add(&result, 3, 10, 20, 30);
...
I want to read numbers(integer type) separated by spaces using scanf() function.
I have read the following:
C, reading multiple numbers from single input line (scanf?)
how to read scanf with spaces
It doesn't help me much.
How can I read numbers with space as delimiter. For e.g. I have following numbers as input 2 5 7 4 3 8 18 now I want to store these in different variables.
Please help.
I think by default values read by scanf with space/enter. Well you can provide space between '%d' if you are printing integers. Also same for other cases.
scanf("%d %d %d", &var1, &var2, &var3);
Similarly if you want to read comma separated values use :
scanf("%d,%d,%d", &var1, &var2, &var3);
scanf uses any whitespace as a delimiter, so if you just say scanf("%d", &var) it will skip any whitespace and then read an integer (digits up to the next non-digit) and nothing more.
Note that whitespace is any whitespace -- spaces, tabs, newlines, or carriage returns. Any of those are whitespace and any one or more of them will serve to delimit successive integers.
int main()
{
char string[200];
int g,a,i,G[20],A[20],met;
gets(string);
g=convert_input(G,string);
for(i=0;i<=g;i++)
printf("\n%d>>%d",i,G[i]);
return 0;
}
int convert_input(int K[],char string[200])
{
int j=0,i=0,temp=0;
while(string[i]!='\0')
{
temp=0;
while(string[i]!=' ' && string[i]!='\0')
temp=temp*10 + (string[i++]-'0') ;
if(string[i]==' ')
i++;
K[j++]=temp;
}
return j-1;
}
It should be as simple as using a list of receiving variables:
scanf("%i %i %i", &var1, &var2, &var3);
With this solution, it's possible to read positive and negatives integers:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFFER_SIZE 50
int convert_input (int * v, char * buffer) {
int len = 0, i = 0, temp = 0, positive_or_negative_one = 1;
while(buffer[i]!='\0') {
temp = 0;
if (buffer[i] == '-'){
positive_or_negative_one = -1;
i++;
} else {
while(buffer[i] != ' ' && buffer[i] != '\0')
temp = temp*10 + (buffer[i++]-'0');
if(buffer[i]==' ')
i++;
v[len++] = temp * positive_or_negative_one;
positive_or_negative_one = 1;
}
}
return len;
}
int main(int argc, char const *argv[]) {
int *a = NULL;
int count_a, len=0;
char buffer[BUFFER_SIZE];
printf("Input numbers here: ");
gets(buffer);
for (int i = 0; i < strlen(buffer); i++) {
if (buffer[i] == ' '){
len+=1;
}
}
a = (int*) malloc(sizeof(int) * len + 1);
count_a = convert_input(a, buffer);
for (int i = 0; i < count_a; i++) {
printf("%d\n", a[i]);
}
free(a);
return 0;
}
Input and output example:
Input numbers here: 1 2 3 -4 10
1
2
3
-4
10