0
votes

I'm not sure where I'm messing up so I've given a summary of each function so my logic can be checked!

The main program takes arguments from the command line and stores them in char pointer array.

The correct command to run program is ./re-do_hw4_prob6 filename. (filename is sears_kmart_stores_closing_2019.txt in this case)

After checking if argument number is correct, the file is opened.

A while loop copies strings of text from file to buffer until NULL is met.

Then the function getState() is called. The state is printed.

The file is closed.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#include "redo_hw4_functs.h"


int main(int argc, char* argv[])
{
    char** states;
    FILE* pFile;
    char buffer[80];
    int i = 0;
    
    
    
    if(argc < 2){
        printf("Too few arguments! \n");
    }
    else if(argc > 2){
        printf("Too many arguments! \n");
    }
    
   
    pFile = fopen(argv[1], "r");
    
    states = malloc(50*sizeof(char));
    
    for (i = 0; i < 50; i++)
    {
    states[i] = malloc(3*sizeof(char));
    
    while(fgets(buffer, sizeof(buffer), pFile) != NULL)
    {
        
        getState(states[i], buffer);
        
        printf("State: %s \n", states[i]);
        
    }
        
        
        }
    
    
    
    fclose(pFile);
    
}

The getState() function takes in two char arrays. One to read from the other to copy too.

It tokenizes the string being read from using a comma, a tab, and a new line as the delimiters. -> ",\t\n"

On the last token it copies the last two chars to the empty string array.

//accepts a line of string formatted as expected and stores the store state in char file ¡OJO! This is the hardest one because you cant rely on delimeters alone to find state 
void getState(char strState[], char strLine[])
{
    int i;
    char* token;
    char delim[] = ",\t\n";
    
    token = strtok(strLine, delim);
    token = strtok(strLine, delim);
    token = strtok(strLine, delim);
    
    for(i = (strlen(token) - 2); i < strlen(token); i++)
    {
        strState[i] =token[i];
    }
    
}

I have also included my other functions to see if there are any other mistakes to be corrected.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>


#include "redo_hw4_functs.h"



//accepts a line of string formatted as expected and stores the store name in char file
void getName(char strName[], char strLine[])
{
    char* token;
    char delim[] = " ,\t\n";
    
    token = strtok(strLine, delim);
    
    while(token != NULL)
    {
        if(strcmp(token, "sears") == 0 || strcmp(token, "kmart"))
        {
            strcpy(strName, token);
            break;
        }
        
        token = strtok(NULL, delim);
    }
    
    
    
    
}

//accepts a line of string formatted as expected and stores the store address in char file
void getAddress(char strAddress[], char strLine[])
{
    
    char* token;
    char delim[] = ",\t\n";
    
    token = strtok(strLine, delim);
    
    while(token != NULL)
    {
        if(isdigit(token[0]) && isalpha(token[sizeof(token)-1]))
        {
            strcpy(strAddress, token);
            break;
        }
        
        token = strtok(NULL, delim);
    }
    
}

//accepts a line of string formatted as expected and stores the store city in char file
void getCity(char strCity[], char strLine[])
{
    int i;
    char* token;
    char delim[] = ",\t\n";
    
    token = strtok(strLine, delim);
    token = strtok(strLine, delim);
    token = strtok(strLine, delim);
    
    for(i = 0; i < (strlen(token) - 3); i++)
    {
        strcpy(strCity[i], token[i]);
    }
    
    
    
    
    
    
}

//accepts a line of string formatted as expected and stores the store state in char file ¡OJO! This is the hardest one because you cant rely on delimeters alone to find state 
void getState(char strState[], char strLine)
{
    int i;
    char* token;
    char delim[] = ",\t\n";
    
    token = strtok(strLine, delim);
    token = strtok(strLine, delim);
    token = strtok(strLine, delim);
    
    for(i = (strlen(token) - 2); i < strlen(token); i++)
    {
        strcpy(strState[i], token[i]);
    }
    
}

Here is an example of input text that is to be read:

Kmart, 217 Forks Of River Pkwy, Sevierville TN
Kmart, 4110 E Sprague Ave, Spokane WA
Kmart, 1450 Summit Avenue, Oconomowoc WI
Sears, 2050 Southgate Rd, Colorado Spgs CO
Sears, 1650 Briargate Blvd, Colorado Spgs CO
Sears, 3201 Dillon Dr, Pueblo CO

Here is an example of what the program is expected to be outputting:

State:TN State:WA State:WI State:CO State:CO State:CO

Here is an example of what the program is outputting:

enter image description here

1
Note: "After checking if argument number is correct, the file is opened." --> file open attempt occurs even if argc is not correct. - chux - Reinstate Monica
states[i] makes no sense - states is not initialized. - KamilCuk
initialized states but I can't seem to copy state abbreviations to it. @KamilCuk - Forrest Brown
states = malloc(50*sizeof(char)); should have been states = malloc(50*sizeof(char*)); . Or, better is states = malloc(50 * sizeof *states); - M. Nejat Aydin
@ForrestBrown Do not use an image, and post the expected output, not the actual output. - M. Nejat Aydin

1 Answers

0
votes

I assume that you want not only the status but also all the other fields so that you can deal with them later.

The code below may be quite different from yours, but I think that it is easier to use a single function to read each record.

The function read_data() reads data from the file pointer fp and store them in data, which is a pointer to a predefined struct data_t.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define BUFFER_SIZE 1024

typedef struct {
    char name[64];
    char addr[64];
    char city[64];
    char state[8];
} data_t;

int read_data(FILE *fp, data_t *data) {
    char buffer[BUFFER_SIZE];

    // Read a record. If end-of-file is read, return -1.
    if (fgets(buffer, BUFFER_SIZE, fp) == NULL) {
        return -1;
    }

    char delim[] = ",\t\n";

    // Find the name of the record.
    char *token = strtok(buffer, delim);
    strcpy(data->name, token);

    // Find the address of the record.
    token = strtok(NULL, delim);
    while (*token == ' ') {
        ++token;
    }
    strcpy(data->addr, token);

    // Find the city and status of the record.
    // We cannot split them by strtok() easily, so we handle it later.
    token = strtok(NULL, delim);
    while (*token == ' ') {
        ++token;
    }

    // Find the position of the state.
    char *ptr = token;
    while (*ptr != '\0') {
        ++ptr;
    }
    ptr -= 2;
    strcpy(data->state, ptr);

    // Use NULL to separate the city and the state so that we can use strcpy().
    while (*(ptr - 1) == ' ') {
        --ptr;
    }
    *ptr = '\0';

    // Copy the city field.
    strcpy(data->city, token);
    return 0;
}

int main(int argc, char *argv[]) {
    if (argc != 2) {
        fprintf(stderr, "The number of arguments is incorrect.\n");
        fprintf(stderr, "Usage: %s filename\n", argv[0]);
        return -1;
    }
    FILE *fp = fopen(argv[1], "r");
    data_t *data = malloc(sizeof(data_t));
    while (read_data(fp, data) == 0) {
        printf("State: %s\n", data->state);
    }
    free(data);
    fclose(fp);
    return 0;
}

The way to read data is hard-coded, so if the input format is different, you may need to change the content of read_data(), but it works well for your sample input.