0

I'm writing a program that is supposed to search for a name in a CSV file and copy the record (all the info on the same line as the name) that goes along with it.

For example, if CSV file contains:

Bob, 13, 12345612
Eli, 12, 21398743

I would input "Bob" to get the first line, and copy this into an array called "record".

So far my code is as follows:

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

void FindRecord(char *a, char *b, char c[]);

void main(void){

    char arrayName[100];
    char arrayNewname[100];
    char *name = arrayName;
    char *newname = arrayNewname;
    char record[1000];

    printf("Please input a name in the phonebook: ");
    scanf("%s", name);

    printf("Please input a replacement name: ");
    scanf("%s", newname);

    FindRecord("phonebook.csv",name,record);
    }

    void FindRecord(char *filename, char *name, char record[]){

    //Create temp array of max size 
    char temp[1000];

    //Open file
    FILE *f = fopen(filename, "r");
    //Make sure file exists 
    if (f == NULL){
        printf("File does not exist");
        fclose(f);
        exit(1);
    }

    //While 
    while(!feof(f)){
        //Read one line at a time   
        fgets(temp, 1000, f); 
        int i = 0;
        int *p;
        for(int i = 0; i < 1000; i++){
            if(temp[i] == *name){
                record[i] = temp[i];
                name++;
            }
            size_t n = (sizeof record /sizeof record[0]);
            if(temp[i] == *name){
            *p = temp[i + n];
            }
        }
    }   
    printf("%s", record);
    fclose(f);
}

Basically, I've found Bob and copied Bob, but do not understand how to proceed using pointers (not allowed to use string.h) and copying the rest of the line. I've been trying to play around with the length of the word once Ive found it but this isn't working either because of pointers. Any help/hints would be appreciated.

David C. Rankin
  • 69,681
  • 6
  • 44
  • 72
turkr
  • 23
  • 7

2 Answers2

0

When you are not allowed to use string.h you have to compare strings char by char. Start by having a loop to find the name.

See: Compare two strings character by character in C

And then copy the rest of the record. Either char by char or with more advance functions like memcpy: https://www.techonthenet.com/c_language/standard_library_functions/string_h/memcpy.php

Now who is int *p ?

You didn't initialized this pointer. You have to either malloc it or assign it to an existing memory. See for more information: https://pebble.gitbooks.io/learning-c-with-pebble/content/chapter08.html

I think you should read more about pointers and then things will work much better for you.

0

Not being allowed to use string.h is a good exercise in computing the string lengths manually (necessary to remove the trailing '\n' from the lines read with fgets) and also a good exercise for manual string comparisons.

For example, if you are reading lines into buf, you can use a simple for loop to get the length of buf, e.g.

    int blen = 0;
    for (; buf[blen]; blen++) {}        /* get line length */

(note: you find the length of name, say nlen in a similar manner)

Then having the length in blen, you can easily check that the final character in buf is the '\n' character and remove it by overwriting the newline with the nul-terminating character, e.g.

    if (blen && buf[blen - 1] == '\n')  /* check/remove '\n' */
        buf[--blen] = 0;                /* overwrite with '\0' */

The remainder of your findrecord function is just a matter of iterating forward over each character looking for the character that is the first character in name. Once found, you simply compare then next nlen character to see if you have found name in buf. You can easily do that with:

            char *np = name,            /* pointer to name */
                *bp = p;                /* current pointer in buf */
            ...
            for (i = 0;     /* compre name in buf */
                i < nlen && *np && *bp && *np == *bp; 
                i++, np++, bp++) {}
            /* validate nlen chars match in buf */
            if (np - name == nlen && *(np-1) == *(bp-1)) {

One you have validated you found name in buf, simply copy buf to record insuring your nul-terminate record when done copying buf, e.g.

            if (np - name == nlen && *(np-1) == *(bp-1)) {
                bp = buf;
                for (i = 0; buf[i]; i++)    /* copy buf to record */
                    record[i] = buf[i];
                record[i] = buf[i];         /* nul-terminate */
                return record;              /* return record */
            }

Putting it altogether, you could do something similar to the following:

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

enum { MAXC = 100, MAXL = 1000 }; /* if you need constants, define them */

char *findrecord (FILE *fp, char *name, char *record);

/* main is type 'int', and has arguments -- use them */
int main (int argc, char **argv) {

    char name[MAXC] = "",
        replace[MAXC] = "",
        record[MAXL] = "",
        *matched;
    FILE *fp = argc > 1 ? fopen (argv[1], "r") : NULL;

    if (!fp) {  /* validate file open for reading */
        fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
        return 1;
    }
    /* prompt, read, validate name */
    printf ("Please input a name in the phonebook: ");
    if (scanf ("%99[^\n]%*c", name) != 1) {
        fprintf (stderr, "error: invalid input - name.\n");
        return 1;
    }
    /* prompt, read, validate replace */
    printf("Please input a replacement name: ");
    if (scanf ("%99[^\n]%*c", replace) != 1) {
        fprintf (stderr, "error: invalid input - replace.\n");
        return 1;
    }
    /* search name, copy record, return indicates success/failure */
    matched = findrecord (fp, name, record);
    if (fp != stdin) fclose (fp);   /* close file if not stdin */

    if (matched) {  /* if name matched */
        printf ("record : '%s'\n", record);
    }

    return 0;   /* main() returns a value */
}

char *findrecord (FILE *fp, char *name, char *record){

    char buf[MAXL] = "";                /* buf for line */

    while (fgets (buf, MAXL, fp)) {     /* for each line */
        char *p = buf;
        int blen = 0;
        for (; buf[blen]; blen++) {}        /* get line length */
        if (blen && buf[blen - 1] == '\n')  /* check/remove '\n' */
            buf[--blen] = 0;                /* overwrite with '\0' */
        for (; *p && *p != '\n'; p++)       /* for each char in line */
            if (*p == *name) {              /* match start of name? */
                char *np = name,            /* pointer to name */
                    *bp = p;                /* current pointer in buf */
                int i = 0,                  /* general 'i' var */
                    nlen = 0;               /* name length var */
                for (nlen = 0; name[nlen]; nlen++) {}   /* name length */
                for (i = 0;     /* compre name in buf */
                    i < nlen && *np && *bp && *np == *bp; 
                    i++, np++, bp++) {}
                /* validate nlen chars match in buf */
                if (np - name == nlen && *(np-1) == *(bp-1)) {
                    bp = buf;
                    for (i = 0; buf[i]; i++)    /* copy buf to record */
                        record[i] = buf[i];
                    record[i] = buf[i];         /* nul-terminate */
                    return record;              /* return record */
                }
            }
    }

    return NULL;    /* indicate no match in file */
}

Example Use/Output

$ ./bin/findrec dat/bob.csv
Please input a name in the phonebook: Bob
Please input a replacement name: Sam
record : 'Bob, 13, 12345612'

Non-Match Example

$ ./bin/findrec dat/bob.csv
Please input a name in the phonebook: Jerry
Please input a replacement name: Bob

Look things over and let me know if you have further questions.

David C. Rankin
  • 69,681
  • 6
  • 44
  • 72