How to input string tokens into a 2d array? - c

Trying to get a list of inputs with delimiter "|":
Public|Jane|Q|Ms.|600|Maple Street|Your Town|Iowa|12345
And then would like to input them into a 2d array (customerData) that I can manipulate.
I realize I'm missing int main() and code for reading file/input. Just including the relevant code. I can get the input, its the putting into customerData getting out of that I'm struggling with.
#define INPUT_LENGTH 128
#define FIELD_LENGTH 30
#define NUM_FIELDS 9
char input[INPUT_LENGTH];
char customerData[NUM_FIELDS][FIELD_LENGTH];
int element = 0;
int customer = 0;
while ( fgets( input, INPUT_LENGTH, data ) != NULL ) {
char* token = strtok(input, "|"); // start tokeninzing
while (token) { // end of string last token is NULL
strcpy(customerData[customer][element], token);
token = strtok(NULL, "|");
element++;
}
customer++;
}
for (int i = 0; i < entry; i++) {
for (int k = 0; k < element; k++) {
printf("%s\n", customerData[i][k]);
}
}
I'm expecting output like this:
Public
Jane
Q
Ms.
600
Maple Street
Your Town
Iowa
12345

the posted code keeps adding 1 to element, even when it is a new line/new customer.
Suggest, after the statement:
customer++;
to insert the statement:
element = 0;
also regarding:
char customerData[NUM_FIELDS][FIELD_LENGTH];
I would expect the first part of the array to be a customer number, then NUM_FIELDS and then FIELD_LENGTH
Also, for clarity suggest element be replaced with fieldNum

Related

Segmentation Fault when My Code Executes the printf() in c

below I have posted my code. When I compile I receive no errors, and only one warning about variables I haven't used yet. the code works all the way to the line in code where it starts to print. I have tested all the sections and I believe that one is at fault. please let me know what I am doing wrong so I can fix it.
#include <stdio.h>
#include <string.h>
#define NUM_LINES 37
#define LINE_LENGTH 60
void select_sort_str(char list[NUM_LINES][LINE_LENGTH], int n);
int alpha_first(char list[NUM_LINES][LINE_LENGTH], int min_sub, int max_sub);
int main (void){
//store each line in an array of strings
FILE *inp;
FILE *outp;
char hurr[NUM_LINES][LINE_LENGTH];
;
inp = fopen("hurricanes.csv","r");
outp = fopen("out.txt","w");
//read in lines from file
for (int i = 0; i<NUM_LINES; i++){
fgets(hurr[i], LINE_LENGTH, inp);
}
inp = fopen("hurricanes.cvs","r");
//printf("%s", hurr[0]);
//define function
select_sort_str(hurr, NUM_LINES);
return(0);
}
int
alpha_first(char list[NUM_LINES][LINE_LENGTH], // input - array of pointers to strings
int min_sub, // input - min and max subscripts of
int max_sub) // portion of list to consider
{
int first, i;
first = min_sub;
for (i = min_sub + 1; i <= max_sub; ++i) {
if (strcmp(list[i], list[first]) < 0) {
first = i;
}
}
return (first);
}
/*
* Orders the pointers in an array list so they access strings in
* alphabetical order
* Pre: first n elements of list reference string of uniform case;
* n >= 0
*/
void
select_sort_str(char list[NUM_LINES][LINE_LENGTH], // input/output - array of pointers being
// ordered to acces strings alphabetically
int n) // input - number of elements to sort
{
int fill, // index of element to contain next string in order
index_of_min; // index of next string in order
char *temp;
char temp1[NUM_LINES][LINE_LENGTH];
for (fill = 0; fill < n - 1; ++fill) {
index_of_min = alpha_first(list, fill, n - 1);
if (index_of_min != fill) {
temp = list[index_of_min];
list[index_of_min][LINE_LENGTH] = list[fill][LINE_LENGTH];
strncpy(temp1[index_of_min], list[index_of_min], LINE_LENGTH);
temp1[fill][LINE_LENGTH] = *temp;
}
}
char *name;
char *cat = 0;
char *date;
for (int i = 0; i<NUM_LINES; i++){
name = strtok(NULL, ",");
cat = strtok(NULL, "h");
date = strtok(NULL, " ");
printf("%s %s %s\n", name, cat, date);
}
// for( int i =0; i<NUM_LINES; i++){
// printf("%s", list[i]);
// }
}
The only first parameter you ever pass to strtok is NULL. You never actually give it anything to parse. Did you perhaps mean strtok(temp1[i], ",");?
Also, why no error checking? It's much easier to find bugs in code with error checking.

How to convert using atoi and strtok with multidimesional arrays?

Okay so i have this mltidim array filled with these numbers,
i wish to convert them into ints at the locations
So its gonna be a int multidim arrayint intarray[2][5][12];
Any tip on getting the converter to solve the issue? ive been on this problem a while and it
feels like im close!!
char chararray[2][5][40] =
{
{
{"307,07,33,307,11,44,307,12,31,307,16,10"},
{"308,07,52,308,11,52,308,12,35,308,16,18"},
{"309,07,24,309,11,40,309,12,30,309,16,14"},
{"310,07,15,310,11,38,310,12,36,310,16,27"},
{"311,07,12,311,11,47,311,12,30,311,16,12"}
},
{
{"314,07,12,314,11,34,314,12,27,314,16,52"},
{"315,07,15,315,11,49,315,12,31,315,16,13"},
{"316,07,59,316,11,44,316,12,38,316,16,42"},
{"317,07,52,317,11,41,317,12,30,317,16,12"},
{"318,08,03,318,11,32,318,12,39,318,16,07"}
}
};
And this is how i am trying to convert but it doesnt even let me debug just a weird error pops up..
int intarray[2][5][12];
for(int i = 0; i < 2 ; i++){
for(int j = 0; j < 5;j++){
for(int k = 0; k < 40;k++){
intarray[i][j][k] = atoi(strtok(chararray[i][j][k],","));
}
}
}
intarray[i][j][k] for i==0, j==0, k==0, represents 3 which is the the character residing at intarray[0][0][0]. This is a single char and cannot be processed using strtok().
What you really want to pass to strtok() is a complete null terminated string:
char chararray[0][0]
which is the 40 character buffer containing "307,07,33,307,11,44,307,12,31,307,16,10".
But because you probably do not want to destroy the array, you should start of by getting a duplicate of the string, something like this:
int intarray[2][5][12] = {{0}};//zero before using
int i=0;
char *dup = strdup(chararray[0][0]);//in your actual code this will be in
//a loop of `i,j` indexes, each one
//yielding the character buffers:
//{"307,07,33,307,11,44,307,12,31,307,16,10"},
//{"308,07,52,308,11,52,308,12,35,308,16,18"},
//{"309,07,24,309,11,40,309,12,30,309,16,14"},
//{"310,07,15,310,11,38,310,12,36,310,16,27"},
//{"311,07,12,311,11,47,311,12,30,311,16,12"}
//{"314,07,12,314,11,34,314,12,27,314,16,52"},
//{"315,07,15,315,11,49,315,12,31,315,16,13"},
//{"316,07,59,316,11,44,316,12,38,316,16,42"},
//{"317,07,52,317,11,41,317,12,30,317,16,12"},
//{"318,08,03,318,11,32,318,12,39,318,16,07"}
if(dup)
{
tok = strtok(dup, ",\n");
while(tok)
{
intarray[0][0][i] = atoi(tok);
tok = strtok(NULL, ",\n");
i++;
}
free(dup);//so you can use it again and again for the other sub-strings.
....
Following this approach, all of the other strings can be parsed into intarray
Each chararray[i][j] is a string - chararray[i][j][k] is a single character in that string. Unfortunately, you're passing the single character to strtok when it expects the address of the first element of the string.
When you're tokenizing repeated elements in a string, you only pass the base address once, then pass NULL for the remainder of the string. So your loop would need to be
for(int i = 0; i < 2 ; i++){
for(int j = 0; j < 5;j++){
intarray[i][j][0] = atoi( strtok( chararray[i][j], "," ) );
for(int k = 1; k < 40;k++){
intarray[i][j][k] = atoi( strtok( NULL, "," ) );
}
}
}
Note that this assumes your input is always well-formed - there's no sort of error or sanity checking.

Extracting words from a string into dynamic 2D char array

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);
// ^--------------------^

How to check first letter of one string with last letter of another string inside of same char array

How can I complete the function canArrangeWords() ?
Question : Given a set of words check if we can arrange them in a list such that the last letter of any word and first letter of another word are same. The input function canArrangeWords shall contain an integer num and array of words arr. num denotes the number of word in the list (1<=num<=100). arr shall contain words consisting of lower case letters between 'a' - 'z' only . return 1 if words can be arranged in that fashion and -1 if cannot.
Input : 4 pot ten nice eye
output : 1
input : 3 fox owl pond
output: -1
Please help me complete this program .
**
#include<stdio.h>
#include<string.h>
int canArrangewords(int,char [100][100]);
void main(){
int n ,count=0 , i ;
char arrayS[100][100];
scanf("%d",&n);
for (i = 0; i < n; ++i)
{
scanf("%s",arrayS[i]);
}
for(i=0;i<n;i++)
{
printf("%s",arrayS[i]);
printf("\n");
}
printf("%c\n",arrayS[2][4]);
canArrangewords(n , arrayS);
}
int canArrangewords(int n,char arrayS[100][100]){
int i , j ;
for ( i = 0; i < n; i++)
{
for ( j = i+1 ; j < strlen(arrayS[j+1]); i++)
{
int flag = strlen(arrayS[j+1]) - 1;
int temp = strcmp(arrayS[i][0],arrayS[j][flag]);
}
}
}
}
Well, first of all think of the way you can reach that answer.
If you only need to know if they can or can not be arranged and you do not have to do so your self you can use an empty array of int array[26] for each letter a-z.
The rule is that from all the first and last letters for all the words only two MAY appear an odd amount of times - the first letter of first word in list and the last letter in the last word in the list, the rest MUST appear an even amount of times. I would add a check to make sure the letters are lowercase as well. good luck!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MINASCII 97
#define LETTERS 26
void UpdateArray(char letter, int* arr)
{
if(arr[letter - MINASCII] == 0)
{
++arr[letter - MINASCII];
}
else
{
--arr[letter - MINASCII];/*for each second time same letter is seen reduce back to zero */
}
}
int canArrangewords(int wordNum, char* wordArr[])
{
int arr[LETTERS] = {0};
int i = 0;
int count = 0 ;
char first;
char last;
char* string;
for (i= 0; i< wordNum; ++i)
{
string = wordArr[i];
first = string[0];
last = string[strlen(string)-1];
UpdateArray(first, &arr[0]);
UpdateArray(last, &arr[0]);
}
for(i = 0; i< LETTERS; ++i)
{
count+=arr[i];
}
if(count == 2 || count == 0)/*either once each or twice -see word1 example in main*/
{
return 1;
}
return -1;
}
int main()
{
int i = 0;
char* words[] = {"pot", "ten", "nice", "eye"};
char* words1[] = {"pot", "ten", "nip"};
char* words2[] = {"fox", "owl", "pond"};
i = canArrangewords(4,words);
printf("%d\n", i);
i = canArrangewords(3,words1);
printf("%d\n", i);
i = canArrangewords(3,words2);
printf("%d\n", i);
return 0;
}
Change your array of words into an array of pointers to words. Then you can simply exchange the pointers.
To speed things up, instead of a pointer to a word, have it point to a structure:
struct WORD {
char *firstchar; // begin of word
char *lastchar; // last char of word
} *words[100]; // array of 100 pointers to words
To read the words:
char buf[100];
for (i = 0; i < n; ++i)
{
scanf("%s",buf);
int len= strlen(buf);
words[i]= malloc(sizeof(struct WORDS));
words[i]->firstchar= malloc(len+1);
strcpy(words[i]->firstchar, buf);
words[i]->lastchar= words[i]->firstchar + len-1;
}
Now compare and sort:
if (*words[i]->lastchar == *words[j]->firstchar) {
struct WORDS *tmp= words[i+1];
words[i+1]= words[j];
words[j]= tmp;
}
Do this in a loop, a kind of bubble sort. I leave that to you.

Fill dynamically sized array in C++ and use the values

I'd like to fill a char-array dynamically and check whether the contained values are valid integers, here's what I got so far:
for(int i = 0; i < 50000; i++)
{
if(input[i] == ',')
{
commaIndex = i;
}
}
commaIndex is the index of a comma inside a file, numerical values should have been entered before a comma, file looks like this: -44,5,19,-3,13,(etc), it's important for this part:
char *tempNumber = new char[commaIndex];
Fill tempNumber (which should presumably be just as big as the number due to my dynamic allocation) so I don't have a number in a size 50000 char-array (named input).
for(int i = 0; i < commaIndex; i++)
{
cout << i << "\n";
tempNumber[i] = input[i];
}
And now I want to use it:
if(!isValidInteger(tempNumber))
{
cout << "ERROR!\n";
}
Unfortunately, tempNumber always seems to be of size 4 irregardless of the value of "commaIndex", i.e. I get the following output:
(Inputdata: 50000,3,-4)
commaIndex: 5
content of tempNumber: 5000 (one 0 missing)
commaIndex: 1
content of tempNumber: 3²²² (notice the 3 ^2s)
commaIndex: 2
content of tempNumber: -4²²
Any ideas?
One more thing: This is for a homework assignment and I am not allowed to use any object-oriented element of C++ (this includes strings and vectors, I've been there and I know it would be SO easy.)
Thanks,
Dennis
You might be interested by the strtol function.
You may also consider using strtok() with sscanf(). Notice, that strtol() does not allow you to check for errors since it simply returns (perfectly valid) value 0 on parse error. On the other hand, sscanf() returns number of successfully read items, so you may easily check if there was an error while reading a number.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int i = 0;
char str[] = "1,2,-3,+4,a6,6";
/* calculate result table size and alloc */
int max = 1;
char* tmp = str;
while (*tmp)
if (*tmp++ == ',')
++max;
int* nums = malloc(sizeof(int) * max);
/* tokenize string by , and extract numbers */
char* pch = strtok(str, ",");
while (pch != NULL) {
if (sscanf(pch, "%d", &nums[i++]) == 0)
printf("Not a number: %s\n", pch);
pch = strtok(NULL, ",");
}
/* print read numbers */
for (i = 0; i < max; ++i)
printf("%d\n", nums[i]);
free(nums);
return 0;
}

Resources