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]);
Related
I will preface this with the fact that this was once working. I added a print statement (now gone) that simply asked the user to input strings.
The input is done through the following method:
./Project aa b
aa was the code to be replaced, and b was going to be the letter replacing it for any occurrences in the user's input.
so for
./project Timmy Johhny
Timmy strolled through the park
the output would be
Johhny strolled through the park.
And as I said, it did work, and after it just printed spaces.
My code looks as follows:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char * isMatch(char* os, char* ns, char* us){
int i;
int oslen, nslen, uslen;
int it = 0;
uslen = strlen(us);
oslen = strlen(os);
nslen = strlen(ns);
for(i=0; i < uslen; i++){
if(strstr(&us[i], os) == &us[i]){
it = it + 1;
i = i + oslen - 1;
}
}
char *ans = malloc(uslen + nslen * it);
int anslen = uslen + nslen * it;
i = 0;
while(*us){
if(strstr(us, os) == us){
strcpy(&ans[i], ns);
i = i + nslen;
us = us + oslen;
}
else
ans[i++] = *us++;
}
return ans;
}
int main(int arg1, char * argp[]){
char input[100];
int i;
char c;
while(1){
if(scanf("%c",&c)==EOF){
break;
}
if( (input[0]=c) != '\n'){
for(i=1;i<100;i++){
scanf("%c", &input[i]);
if(input[i] == '\n'){
break;
}
// char *match = isMatch(argp[1],argp[2],&input[i]);
// printf("%s", match);
// free(match);
}
char *match = isMatch(argp[1],argp[2],&input[i]);
printf("%s", match);
free(match);
}
}
}
Is there just a small error I made, or is it something larger.
I tried to move the printf in and out of a for loop amongst everything else, and simply got increasingly strange outputs.
Thank you!
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 am trying to read in a string from a file, then parse the contents of the string to determine how many children to create with fork(), and send each child a section of the string.
int main() {
FILE * fp = fopen("Makefiletest", "r");
char * s;
int i;
char * e;
int c;
for (c = 0; c < 7; c++) {
fgets(s, 128, fp);
}
//e = strchr(s, ":");
//i = (int)(e - s);
//printf("index of : is %d\n", i);
printf("%s", s);
for (i = 0; s[i]; s[i]=='.' ? i++ : *s++);
printf("%d\n", i);
return 0;
}
which retrieves the line "maketools.a: parse.o find.o"
maketools.a is a 2nd generation child (that will have received the string "maketools.a" from its parent), and needs to create 2 new 3rd generation children one with the string "parse.o" the other with "find.o".
I ran into a dead end when I was unable to get the index of : due to segmentation faults (it is commented out and replaced with an attempt I was trying to do with counting instead of strings (it failed)), which prevented me from dividing up the string.
UPDATE
int main() {
FILE * fp = fopen("Makefiletest", "r");
char * s[256];
int i, index, ind;
char * e;
int c;
for (c = 0; c < 7; c++) {
fgets(s, 128, fp);
}
e = strchr(s, ":");
index = (int)(e - s);
printf("index of : is %d\n", index);
printf("%s", s);
return 0;
}
UPDATE 2
int main () {
char fgets_string[256];
char * fgets_string_ptr = fgets_string;
strcpy(fgets_string_ptr, " maketools.a: parse.o find.o ");
char depen[6][128]; //[0][] is root, 1+ are dependencies
char * depen_ptr;
int c;
while (isspace(* fgets_string_ptr)) {//removes leading whitepace
fgets_string_ptr++;
}
for (c = 0; strlen(fgets_string_ptr) > 0; c++) {
if (c == 0)
strtok_r(fgets_string_ptr, ":", &depen_ptr);
else {
strtok_r(fgets_string_ptr, " ", &depen_ptr);
}
while (isspace(* depen_ptr)) {//removes leading whitespace
depen_ptr++;
}
strcpy(depen[c], fgets_string_ptr);
strcpy(fgets_string_ptr, depen_ptr);
//printf("%s\n", depen[c]);
}
printf("%s\n", depen[0]);
printf("%s\n", depen[1]);
printf("%s\n", depen[2]);
return 0;
}
Below is a different approach to achieve what you want... Output of the code is
~/code/str % clang a.c -I../zstring -Wno-unused-value
~/code/str % ./a.out
maketools.a
parse.o
find.o
~/code/str %
Instead of locating the : character first and dealing with spaces, you can split your string into tokens by using (space) as the separator first, and then for the first string, you can remove : character.
The code below uses a string library I maintain, and can be downloaded from https://github.com/fnoyanisi/zString (available with BSD license)
#include <stdio.h>
#include <zstring.h>
int main(){
char s[]="maketools.a: parse.o find.o";
printf("%s\n",zStrrmv(zStrtok(s," "),":"));
printf("%s\n",zStrtok(NULL," "));
printf("%s\n",zStrtok(NULL," "));
return 0;
}
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