I´m new to C programming and have a problem:
I have a string:
char input[] = "1000 10 30: 1 2 3";
I want to split input and store value in different arrays, "1000 10 30" in one array and "1 2 3" in different array.
I've tried to use strtok(), but I can´t find the solution to do it.
Somebody know how to do it?
Thanks!
Edit: Thanks, here is rest of the code:
int a1[3];
int a2[3];
char input[] = "1000 10 30:400 23 123";
char*c = strtok(input, ":");
while (c != 0)
{
char* sep = strchr(c, ' ');
if (sep != 0)
{
*sep = 0;
a1[0] = atoi(c);
++sep;
*sep = strtok(sep, " ");
a1[1] = atoi(sep);
++sep;
a2[2] = atoi(sep);
}
c = strtok(0, ":");
I used an example I found here and tried to change it to add more element to an array, but could not make it. the third element is for some reason 0, and I don't understand why. I'm a beginner++ on programming, but mostly C# and I don't used pointers before.
It is unclear to me what you try to do with the pointer sep. And this code
*sep = strtok(sep, " ");
should give you compiler warnings as strtok returns a char pointer and you are trying to store it into a char (aka *sep).
You don't need more than strtok as you can give it multiple delimiters, i.e. you can give it both ' ' and ':' by passing it " :".
So the code could look like this:
int main() {
char input[] = "1000 10 30: 1 2 3";
int a1[3];
int a2[3];
int i = 0;
char* p = strtok(input, " :");
while(p)
{
if (i < 3)
{
a1[i] = atoi(p);
++i;
}
else if (i < 6)
{
a2[i-3] = atoi(p);
++i;
}
p = strtok(NULL, " :");
}
// Print the values
for (int j = 0; j <i; ++j)
{
if (j < 3)
{
printf("a1[%d] = %d\n", j, a1[j]);
}
else if (j < 6)
{
printf("a2[%d] = %d\n", j-3, a2[j-3]);
}
}
}
Output:
a1[0] = 1000
a1[1] = 10
a1[2] = 30
a2[0] = 1
a2[1] = 2
a2[2] = 3
Tip: The above code solves the task but I recommend you take a look at sscanf as it will allow you to read the values with a single line of code.
Related
I have a dynamic char array that contains a string. I'm trying to extract all the words from this string into a dynamic 2d char array. Here's my code:
int rows = 1;
char *input_words = malloc((rows)*sizeof(char));
input_words = lowerCase(getInputWords(MAX_LINE_LEN, input_file)); //retrieves a string of words
char **input_words_tokenized = malloc((wordCount(input_words))*sizeof(char));
for(i = 0; i < wordCount(input_words); i++) {
input_words_tokenized[i] = malloc(MAX_KEY_LEN*sizeof(char));
}
char *t = strtok(input_words, " ");
j = 0;
while(t) {
for(i = 0; i < strlen(t); i++) {
strcpy(&input_words_tokenized[j][i], &t[i]);
printf("%c", input_words_tokenized[j][i]);
}
j++;
t = strtok(NULL, " ");
}
In my output, input_words_tokenized[j][i] only contains the first word or token from input_words. Why aren't the remaining words being tokenized and stored into input_words_tokenized[j][i]?
At least one issue.
Incorrect size calculation.
char **input_words_tokenized =
malloc((wordCount(input_words))*sizeof(char));
// wrong type ^--^
Instead of sizing to the hopefully matching type, size to the referenced type. It is easier to code right, review and maintain.
char **input_words_tokenized =
malloc((wordCount(input_words)) * sizeof *input_words_tokenized);
// ^--------------------^
I have task to make family binary tree. In this task I need to implement some commands (e.g. add,draw,list..) First of all I need to tokenize standard input .For example "add Walburga [f] mother Sirius Black [m]") to find which commands , names,surnames, relationships and genders are entered.
I have done this with strtok function, and now I have array, which contains every separated string from standard input as parameters. But now I need to concatenate name and surname (if exists) as one parameter.
If the input will always have the format:
command fullname1 [gender] relation fullname2 [gender]
I suggest an approach with strchr() to find the first space and call it command_end. Then find the first [ and call position of [ - 1 = fullname1_end etc.
Then you find the length of the token with command_end - command_startfor example and strncpy() the length to an array and so on.
So you would get something like this (I've used very verbose names to avoid comments):
int main(void)
{
char input[] = "add Walburga Granger [f] mother Sirius Black [m]";
char command[30];
char fullname1[30];
char gender1[4];
char rel[30];
char fullname2[30];
char gender2[4];
char* command_start = input;
char* command_end = strchr(input, ' '); // find the first whitespace of input
char* fullname1_start = command_end + 1;
char* gender1_start = strchr(input, '['); // find the first '[' of input
char* fullname1_end = gender1_start - 1;
char* gender1_end = strchr(gender1_start, ' '); // find the first space after gender1 and so on...
char* rel_start = gender1_end + 1;
char* rel_end = strchr(rel_start, ' ');
char* fullname2_start = rel_end + 1;
char* gender2_start = strchr(fullname2_start, '[');
char* gender2_end = strchr(gender2_start, '\0');
char* fullname2_end = gender2_start - 1;
int command_length = command_end - command_start;
strncpy(command, command_start, command_length);
command[command_length] = '\0';
int fullname1_length = fullname1_end - fullname1_start;
strncpy(fullname1, fullname1_start, fullname1_length);
fullname1[fullname1_length] = '\0';
printf("command: %s\n", command);
printf("fullname1: %s\n", fullname1);
}
Output:
command: add
fullname1: Walburga Granger
Another approach would be to iterate over the input trying to find those keys characters along the way, like:
int main(void)
{
char input[] = "add Walburga Granger [f] mother Sirius Black [m]";
char command[30];
char name1[30];
char gender1[4];
char rel[30];
char name2[30];
char gender2[4];
int i = 0;
int j = 0;
// extract command
for (j = 0; i < strlen(input); i++, j++)
{
if (input[i] == ' ')
break;
command[j] = input[i];
}
command[j] = '\0';
i++;
// extract first fullname1
for (j = 0; i < strlen(input); i++, j++)
{
if (input[i] == '[')
break;
name1[j] = input[i];
}
name1[j - 1] = '\0';
// extract gender1
for (j = 0; i < strlen(input); i++, j++)
{
if (input[i] == ' ')
break;
gender1[j] = input[i];
}
gender1[j] = '\0';
and so on....
Third approach to salvage the majority of your code. You would insert this snippet after you get your command tokens.
char fullname1[100];
char fullname2[100];
// build fullname1
strcpy(fullname1, commands[1]);
i = 2;
while (commands[i][0] != '[')
{
strcat(fullname1, " ");
strcat(fullname1, commands[i]);
i++;
}
// build fullname2
i += 2;
strcpy(fullname2, commands[i]);
i++;
while (commands[i][0] != '[')
{
strcat(fullname2, " ");
strcat(fullname2, commands[i]);
i++;
}
printf("%s\n", fullname1);
printf("%s\n", fullname2);
I think sprintf is what you want.
char fullname[strlen(commands[4]) + strlen(commands[5]) + 2]; // plus 2 for ' ' and '\0'
sprintf(fullname, "%s %s", commands[4], commands[5]);
/* fullname = "Sirius Black" */
I am attempting to learn C by myself. I was trying to split an integer into multiple separate integers, e.g. 12345 into 12 and 34 and 5, but I'm unable to find a way to do it.
I already know some Java and programming basics. Would I need to use some kind of do-while or for loop to do this, or can I use an array of an integer?
This dynamically accomplishes what you are looking for! You can set any type of split you want. 2-2-4 or 3-4-5 or anything. (you can basically get a number string from the user and accomplish this task, and turn the temporary string into an integer if you would like later on) :
#include <stdio.h>
#include <string.h>
int main() {
int i; //Counter
char getStr[100];
int NumberToSplit1, NumberToSplit2, NumberToSplit3;
printf("Enter a number: ");
scanf("%s", getStr); //get it as a string
//or you can use scanf("%[^\n], getStr);
printf("How many number splits you want: ");
scanf("%d %d %d", &NumberToSplit1, &NumberToSplit2, &NumberToSplit3);
printf("\n%d-%d-%d split: \n", NumberToSplit1, NumberToSplit2, NumberToSplit3);
for (i = 0; i < NumberToSplit1; i++) {
printf("%c", getStr[i]);
}
printf("\n");
for (i = NumberToSplit1; i < (NumberToSplit1+NumberToSplit2); i++) {
printf("%c", getStr[i]);
}
printf("\n");
for (i = (NumberToSplit1+NumberToSplit2); i < (NumberToSplit1+NumberToSplit2+NumberToSplit3); i++) {
printf("%c", getStr[i]);
}
//If you want to save it in an integer, you can use strcat function to save the temp 2 numbers in a string convert that to integer
//or use http://stackoverflow.com/questions/7021725/converting-string-to-integer-c
printf("\n");
printf("\n");
}
Output:
Enter a number: 12345
How many number splits you want: 2 2 4
2-2-4 split:
12
34
5
Program ended with exit code: 0
Since you want to split an eight digit number in a 2-2-4 shape you can just use integer division and modulo.
Assuming you don't want the negative sign if any :
void split( int input, int output[3] )
{
if ( input<0 )
input = -input;
output[0] = input % 10000;
output[1] = ( input / 10000 ) % 100;
output[2] = input / 1000000;
}
Otherwise, first, to convert the int to a string:
#include <stdio.h>
int n = 12345678;
int len = snprintf(NULL, NULL, "%d", n);
char *digits = malloc(len);
sprintf(digits, "%d", n);
Then you could split the string up various ways, such as:
int a, b, c;
sscanf(digits, "%2d%2d%4d", &a, &b, &c);
Or:
char sa[2], sb[2], sc[4];
char *cp = digits;
sa[0] = *cp++;
sa[1] = *cp++;
sb[0] = *cp++;
sb[1] = *cp++;
sc[0] = *cp++;
sc[1] = *cp++;
sc[2] = *cp++;
sc[3] = *cp++;
printf("%2c %2c %4c\n", sa, sb, sc);
Or:
// Create 3 buffers to hold null-terminated ('\0' terminated) strings
char sa[3] = { 0 } , sb[3] = { 0 }, sc[4] = { 0 };
char *cp = digits;
sa[0] = *cp++;
sa[1] = *cp++;
sb[0] = *cp++;
sb[1] = *cp++;
sc[0] = *cp++;
sc[1] = *cp++;
sc[2] = *cp++;
sc[3] = *cp++;
printf("%s %s %s\n", sa, sb, sc);
Then free your memory:
free(digits);
Etc...
Etc...
Etc...
I have a program I wrote to take a string of words and, based on the delimiter that appears, separate each word and add it to an array.
I've adjusted it to account for either a ' ' , '.' or '.'. Now the goal is to adjust for multiple delimiters appearing together (as in "the dog,,,was walking") and still only add the word. While my program works, and it doesn't print out extra delimiters, every time it encounters additional delimiters, it includes a space in the output instead of ignoring them.
int main(int argc, const char * argv[]) {
char *givenString = "USA,Canada,Mexico,Bermuda,Grenada,Belize";
int stringCharCount;
//get length of string to allocate enough memory for array
for (int i = 0; i < 1000; i++) {
if (givenString[i] == '\0') {
break;
}
else {
stringCharCount++;
}
}
// counting # of commas in the original string
int commaCount = 1;
for (int i = 0; i < stringCharCount; i++) {
if (givenString[i] == ',' || givenString[i] == '.' || givenString[i] == ' ') {
commaCount++;
}
}
//declare blank Array that is the length of commas (which is the number of elements in the original string)
//char *finalArray[commaCount];
int z = 0;
char *finalArray[commaCount] ;
char *wordFiller = malloc(stringCharCount);
int j = 0;
char current = ' ';
for (int i = 0; i <= stringCharCount; i++) {
if (((givenString[i] == ',' || givenString[i] == '\0' || givenString[i] == ',' || givenString[i] == ' ') && (current != (' ' | '.' | ',')))) {
finalArray[z] = wordFiller;
wordFiller = malloc(stringCharCount);
j=0;
z++;
current = givenString[i];
}
else {
wordFiller[j++] = givenString[i];
}
}
for (int i = 0; i < commaCount; i++) {
printf("%s\n", finalArray[i]);
}
return 0;
}
This program took me hours and hours to get together (with help from more experienced developers) and I can't help but get frustrated. I'm using the debugger to my best ability but definitely need more experience with it.
/////////
I went back to pad and paper and kind of rewrote my code. Now I'm trying to store delimiters in an array and compare the elements of that array to the current string value. If they are equal, then we have come across a new word and we add it to the final string array. I'm struggling to figure out the placement and content of the "for" loop that I would use for this.
char * original = "USA,Canada,Mexico,Bermuda,Grenada,Belize";
//creating two intialized variables to count the number of characters and elements to add to the array (so we can allocate enough mmemory)
int stringCharCount = 0;
//by setting elementCount to 1, we can account for the last word that comes after the last comma
int elementCount = 1;
//calculate value of stringCharCount and elementCount to allocate enough memory for temporary word storage and for final array
for (int i = 0; i < 1000; i++) {
if (original[i] == '\0') {
break;
}
else {
stringCharCount++;
if (original[i] == ',') {
elementCount++;
}
}
}
//account for the final element
elementCount = elementCount;
char *tempWord = malloc(stringCharCount);
char *finalArray[elementCount];
int a = 0;
int b = 0;
//int c = 0;
//char *delimiters[4] = {".", ",", " ", "\0"};
for (int i = 0; i <= stringCharCount; i++) {
if (original[i] == ',' || original[i] == '\0') {
finalArray[a] = tempWord;
tempWord = malloc(stringCharCount);
tempWord[b] = '\0';
b = 0;
a++;
}
else {
tempWord[b++] = original[i];
}
}
for (int i = 0; i < elementCount; i++) {
printf("%s\n", finalArray[i]);
}
return 0;
}
Many issues. Suggest dividing code into small pieces and debug those first.
--
Un-initialize data.
// int stringCharCount;
int stringCharCount = 0;
...
stringCharCount++;
Or
int stringCharCount = strlen(givenString);
Other problems too: finalArray[] is never assigned a terminarting null character yet printf("%s\n", finalArray[i]); used.
Unclear use of char *
char *wordFiller = malloc(stringCharCount);
wordFiller = malloc(stringCharCount);
There are more bugs than lines in your code.
I'd suggest you start with something much simpler.
Work through a basic programming book with excercises.
Edit
Or, if this is about learning to program, try another, simpler programming language:
In C# your task looks rather simple:
string givenString = "USA,Canada Mexico,Bermuda.Grenada,Belize";
string [] words = string.Split(new char[] {' ', ',', '.'});
foreach(word in words)
Console.WriteLine(word);
As you see, there are much issues to worry about:
No memory management (alloc/free) this is handeled by the Garbage Collector
no pointers, so nothing can go wrong with them
powerful builtin string capabilities like Split()
foreach makes loops much simpler
1 13 3 4; 5 6 7 8; 9 10 11 12; 2 15 14 0
How can I get numbers from this string in ANSI C?
I tried to separate it with strtok() :
char *vstup = argv[1];
char delims[] = ";";
char *result = NULL;
result = strtok( vstup, delims );
while( result != NULL ) {
printf( "result is \"%s\"\n", result );
result = strtok( NULL, delims );
}
and I got this:
result is "1 13 3 4"
result is " 5 6 7 8"
result is " 9 10 11 12"
result is " 2 15 14 0"
Now I don't know how to get numbers in integers and save them to two-dimensional field (matrix). I need something like this:
field[1][1] = 1
.
.
.
etc.
I'm wondering about atoi(), but I'm not sure, if it would recognize for example "13" as one number..
Use even space as delimiter. For example in ur case this code put the numbers in 2d array of size 4x4
#include<stdio.h>
#include<string.h>
void main()
{
char a[] = "1 13 3 4; 5 6 7 8; 9 10 11 12; 2 15 14 0";
int i=0 ,j=0 , x;
int array[4][4];
char *temp;
temp = strtok(a," ;");
do
{
array[i][j] = atoi(temp);
if(j == 4)
{
i++;
j = 0;
}
j++;
}while(temp = strtok(NULL," ;"));
for(i=0; i<4; i++)
{
for(j=0; j<4 ;j++)
{
printf("%d ",array[i][j]);
}
printf("\n");
}
}
You can do the exact same thing you did for stripping up to the ';' but instead also use ' ' for spaces. Place this result into an array and you can use atoi or whatever you want on the entire array. If you want to put it into a 2-d array you can split the string up to the ';' and then within that loop split each integer into whatever part of the array you want to. Won't write the code as it looks like homework.
One way is to use sscanf:
char* input = ...;
while(*input) {
input += ';' == *input;
int a, b, c, d, n = -1;
sscanf(input, "%d %d %d %d%n", &a, &b, &c, &d, &n);
if(n < 0)
// parsing error
// parsed successfully into a, b, c, d
input += n;
}
Note, that the input string is left unchanged here.