0

I'm new in C language (my 6th day learning C), and this is my 2nd question in here, so I'm trying to save the inputed data from my program to a .csv file using command fwrite below (see the code). But when i opened the csv file, my data only saved to the first cell and its kinda repetitive ( You can see it in the pic below ).

I'm trying to each data to be saved into one cell Like this :

Samuel

Jakarta

13/01/2011

0185-13553131

How can i do it? Thanks For your help :3

Inside of My CSV file

int main () {
struct identitas arr_identitas[max];
struct identitas*ptr;
int x,i,choice,f,pilih,a=0,b,r,y,c,d;
char apusNama [20];
char apusAlamat [20];
char newnama [20];
char newalamat[20];
char newtgl_lahir[20];
char newno_tlp[20];
char nullStr[20] = {"\0"};

FILE *outfile, *infile; //initiation outfile (to write) infile (to open)

outfile = fopen ("Tugas2-5.csv","w"); //name of file, w = write
if (outfile == NULL){
    fprintf(stderr, "\nError opening file\n\n"); //if file not found
    exit(0);
}

infile = fopen ("Tugas2-5.csv","r+"); //name of file, r = read
if (infile == NULL){
    fprintf(stderr, "\nError opening file\n\n"); //if file not found or empty
    exit(0);
}

while (1) {
    printf ("\n \t -*-*-*-*-* WELCOME TO MENU -*-*-*-*-* \t \n"); // MAIN MENU
    printf("\n");
    printf ("1. Memasukkan/Menambahkan Data \n"); // 1. INPUT INITIAL DATA
    printf("2. Menampilkan data \n"); // 2. SHOWING DATA (ALL)
    printf("3. Menampilkan 1 data \n"); // 3. SHOWING DATA (1/SINGLE)
    printf("4. Menghapus data \n"); // 4. DELETING DATA
    printf ("5. Menginput tambahan \n"); //5. INPUTING ADDITIONAL DATA
    printf ("6. Mengedit data \n"); // 6. EDIT EXISTING DATA
    printf("7. Sorting\n"); // 7. SORTING DATA
    printf ("8. Read Data\n");
    printf("9. Exit\n\n\n"); // 8. EXITING DATA
    printf("Enter your choice :  "); scanf("%d",&choice);
    
    switch (choice)
    {
        case 1: // ==> Inputing data from user
            printf ("Masukkan Jumlah Data : "); scanf("%d", &x); // Input max number of data

            ptr = calloc (x, sizeof (arr_identitas[max])) ;
            if (ptr == 0) { 
                printf("Memory not allocated.\n"); //calloc successfukk
                exit(0); 
                }
            else {
                printf("Memory array  successfully allocated \n");
                }

            while (i < x ) {
                printf ("Data ke = %d \n ",i+1); //data n input
                bool err=true;
                bool frr=true;
                int counter = 0;
                while (counter == 0) {
                    fflush(stdin);
                    printf ("Masukkan nama anda : "); gets((ptr+i)->nama); //input name
                    if ( strlen ((ptr+i)->nama ) == 0 ) {
                        printf("# ERROR,TERMINATE PROGRAM # \n"); //if name is empty terminate program
                        exit(0);
                    }
                    else {
                        counter = 1;
                        }
                }   
                printf ("Masukkan alamat anda : "); gets((ptr+i)->alamat); //input address
    
                printf ("Masukkan kode telp anda (xxxx-xxxxxxxxx) : "); gets ((ptr+i)->nomor_telepon); //input phone number
                while(err==true){
                    if((ptr+i)->nomor_telepon[3]!='-'&&(ptr+i)->nomor_telepon[4]!='-'){
                        printf("EROR COBA LAGI.\n");
                        printf("Masukkan kode telp anda (xxxx-xxxxxxxxx): "); gets((ptr+i)->nomor_telepon);
                    }
                    else err=false;
                }
        
                printf ("Masukkan tanggal lahir anda (dd/mm/yyyy) : "); gets ((ptr+i)->tanggal_lahir); //input date of birth
                while(frr==true){
                    if((ptr+i)->tanggal_lahir[2]!='/'||(ptr+i)->tanggal_lahir[5]!='/'){
                        printf("ERROR COBA LAGI.\n");
                        printf("Masukkan tanggal lahir anda (dd/mm/yyyy) : \n\n"); gets((ptr+i)->tanggal_lahir);
                    }
                    else frr=false;
                }
                b = i;
                c = i;
                i++;
                counter = 0;
                fwrite (ptr, sizeof(struct identitas), x, outfile); //writing data to outfile
            }
            break;
David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
  • 2
    You are somewhat using a hammer to write with, or conversely, a pen to drive a nail. Why have you chosen `fwrite` to output *formatted* data? `fwrite` is an *unformatted* output function. While it can be used to output text, you are far better served using a *formatted* (`fprintf()`, etc,) or *character-oriented* (`fputc()`, etc..) function. A *csv* (comma separated values) file is a formatted text file. Also note, you only need a single call to `puts()` to output your entire menu -- there are no conversions and no need for a separate function call per-line of output. – David C. Rankin Nov 30 '20 at 05:44
  • `fflush` is not defined for *input* streams, see: [C11 Standard - 7.21.5.2 The fflush function(p2)](http://port70.net/~nsz/c/c11/n1570.html#7.21.5.2p2) and [fflush(stdin); **leads to undefined behaviour on most systems.**](https://stackoverflow.com/a/38325926/2173917). `fflush(stdin)` is non-portable. There is only one compiler that provides for the explicit non-standard use of `fflush()` which is best avoided. – David C. Rankin Nov 30 '20 at 05:54
  • this code is not a complete code of program i only take the 1st case of my program which is inputing data. About the fwrite and fputs, i didnt know the difference, when and how i should use fwrite or fputs? – Samuel Pandiangan Nov 30 '20 at 06:03
  • Your use of `fwrite (ptr, sizeof(struct identitas), x, outfile);` is correct -- and it appears that the confusion comes from what you are calling CSV. An Excel spreadsheet is not a CSV file. (You can export to CSV, from a spreadsheet, but the records are not natively stored as CSV by Excel.) The picture you show is Excel. Is the file you are reading and writing an export from it? And if it is a CSV export -- then using `fwrite()` to write to the output file will not produce a CSV record. – David C. Rankin Nov 30 '20 at 06:03
  • You have `outfile = fopen ("Tugas2-5.csv","w");` which creates an empty file, followed by `infile = fopen ("Tugas2-5.csv","r+");` which opens the now empty file for reading and writing. This is probably not a good idea. If the intent is to read from `infile` (not shown in the code fragment), it is definitely not a good idea. – Jonathan Leffler Nov 30 '20 at 06:04
  • You normally use `fprintf()` for formatting data, or `fputs()` for pre-formatted data, and `fwrite()` for binary data (normally with a fixed size/format). CSV files normally contain variable-length data fields, and do not contain null bytes — whereas using `fwrite()` on a structure containing strings guarantees null bytes will be present. – Jonathan Leffler Nov 30 '20 at 06:15
  • @DavidC.Rankin my intent is to save the inputed data (name,address,etc) in to the CSV file, in case 1. In case 8, the program will read the inputed data from that CSV file again. – Samuel Pandiangan Nov 30 '20 at 06:16
  • @JonathanLeffler, i create outfile so i have an empty file that can be written. Using the 'w' command in fopen, making it so the file can only be used to write. After that i called infile later in case 8, to read the inputted file again, using the 'r+' command. – Samuel Pandiangan Nov 30 '20 at 06:39
  • OK — that's why I said "probably not a good idea". You seem to have a reason for doing it. I'm not wholly convinced it is a good idea, but you have a reason. Your block of code for `case 1:` is so big it should be in its own function — and so, probably, should the code for each of the other cases in the switch. Indeed, at 60-odd lines, some would argue the block of code is too big for a single function. – Jonathan Leffler Nov 30 '20 at 06:43
  • @JonathanLeffler So, i should make it to function? and about my original question, how should i do it? so when i opened the file it's not showing like that (only use one cell and repetitive). I'm sorry it's only my 6th day learning C by my own.. – Samuel Pandiangan Nov 30 '20 at 07:24
  • Yes, you should probably make the code after `case 1:` (up to but not including the `break`) into a function. I haven't studied your code to see what you'd need to make available to that function. Since you have learned structures, it is probably worth doing. Generally, you should aim to avoid "big" functions, and if you have 8 cases in your switch and 7 of them contain 60 lines of code (the other probably just exits the program and isn't very big), you would have a big function and you should split the code into smaller functions. There'll be exceptions — but as a general rule… – Jonathan Leffler Nov 30 '20 at 07:28
  • If I was going to work out why your code isn't working, I'd need an MCVE ([Minimal, Complete, Verifiable Example](https://stackoverflow.com/help/mcve) — or MRE or whatever name SO now uses) or an SSCCE ([Short, Self-Contained, Correct Example](http://sscce.org/)). Your code is not an MCVE because the `struct identitas` is missing, and you have extraneous code (like the prompts for other options, and some of the file opening code), which means I can't test it. – Jonathan Leffler Nov 30 '20 at 07:34
  • Also, I don't want to spend the time reading it — it's hard to read when formatted as shown. I recommend using `if (ptr[i].nomor_telepon[3] != '-' && ptr[i].nomor_telepon[4] != '-')` instead of what you've got (no spaces and using `(ptr+i)->nomor_telepon[3]`, etc.). My replacement code has white space separating binary operators, but no white space around subscripts or member access operators (`.` and `->`). The subscript notation is easier to read. – Jonathan Leffler Nov 30 '20 at 07:37
  • @JonathanLeffler Thank you, I'll try and change it into function. About the full code, i could send you, if you like, but some of the variables name,etc not using english.But I can try to add comment in english in each command, again, if you like the code. Thanks for your help... – Samuel Pandiangan Nov 30 '20 at 07:39
  • The point of a Minimal, Complete, Verifiable Example is that it is _not_ the full code. It is only the code relevant to your current problem, and it is compilable. You should read the links I gave. You create an MCVE by making a copy of the code that isn't working. You then edit either the copy or the original (but not both) removing extraneous material, making sure it compiles, and still shows the problem. Use a version control system such as Git to keep a record of each change. Iterate until you can't remove anything. Then, maybe, you have an MCVE. It takes work to produce one. – Jonathan Leffler Nov 30 '20 at 07:43
  • I'm not worried about the variable names — I think the text in the messages is in Indonesian, isn't it? (Google Translate agrees) — though there are those who object to non-English text and variable names in SO questions. I've worked with programmers in multiple human languages and names like `strlen` are just as much gibberish as anything you're using. While the character set is ASCII, the names don't matter much to me. But I would much prefer the MCVE. You can look at my profile if you want to send me an MCVE. – Jonathan Leffler Nov 30 '20 at 07:49

0 Answers0