CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 2 of 2 FirstFirst 12
Results 16 to 29 of 29
  1. #16
    Join Date
    Jul 2013
    Posts
    30

    Re: Assigning a value to struct variables?

    @2kaud: Sorry, can you please explain this line:

    if (char *nl = strrchr(acct.name, '\n')) *nl = 0;

    I haven't used that many libraries yet, except for stdio/stdlib/math, so please excuse me. And I'm really confused about the pointers (*). Can I get a layman explanation from you, 2kaud? All the stuff I've read so far can be a little bit too confusing for a beginner like me, unfortunately...

  2. #17
    Join Date
    Jan 2006
    Location
    Singapore
    Posts
    6,765

    Re: Assigning a value to struct variables?

    Quote Originally Posted by riechan
    @2kaud: Sorry, can you please explain this line:

    if (char *nl = strrchr(acct.name, '\n')) *nl = 0;
    That is explained in the last line that 2kaud wrote:
    Quote Originally Posted by 2kaud
    Note that fgets reads the terminating new line so this needs to be removed.
    You may find it somewhat more concise to write:
    Code:
    acct.name[strspn(acct.name, "\n")] = '\0';
    The basic idea is to find (whether by using strrchr or strspn) the newline character, and then replace it with a null character.
    C + C++ Compiler: MinGW port of GCC
    Build + Version Control System: SCons + Bazaar

    Look up a C/C++ Reference and learn How To Ask Questions The Smart Way
    Kindly rate my posts if you found them useful

  3. #18
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,822

    Re: Assigning a value to struct variables?

    Are you using c or c++? The code you are using looks like c but if you're using c++ then it would be better to use c++ strings and streams rather than the c library versions.

    Code:
    if (fp = fopen("acctinfo.txt", "r+")) {
    if fopen succeeds, then a file pointer is returned otherwise it returns null. So this assigns the returned file pointer to fp and tests if it is non-zero.

    Code:
    if (fgets(acct.name, 60, fp) && fscanf(fp, "%19s\n%9s\n%f\n", acct.num, acct.pin, &acct.bal) == 3) {
    fgets(..) will read the next line from the file and put a maximum of 59 chars into acct.name and null terminate it. fgets returns a pointer to acct.name on success or null on failure. fscanf returns the number of arguments actually assigned a value - which should be 3 in this case. So if fgets returns a non-null value and fscanf returns 3 then the test succeeds. Note that fscanf is only evaluated if fgets returns a non-null value.

    Code:
    if (char *nl = strrchr(acct.name, '\n')) *nl = 0;
    strrchr searches from the end of acct.name until it finds a new line ('\n'). If it does find one then it returns a pointer to it otherwise it returns null. So this assigns the returned pointer from strrchr to nl and if this is non-null the test succeeds and then replaces the char pointed to by nl with a 0 which overwrites the \n and terminates the string.

    If you are having trouble with pointers try these

    http://www.learncpp.com/cpp-tutorial...n-to-pointers/
    http://www.cplusplus.com/doc/tutorial/pointers/
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  4. #19
    Join Date
    Jul 2013
    Posts
    30

    Re: Assigning a value to struct variables?

    I was told that using !feof() is a bad thing to do, so I guess I'll stick to my while statement? So the output is still the same. I really don't know what I'm doing wrong here, as to why the extra digits are appearing in the bal variable. I need to get the exact value since I'll be making computations using it...

    I'm using C (in Turbo C) if it makes any difference, by the way.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    #define MAXAMT 999999.99
    
    typedef struct Account{
    	char name[60];
    	char num[20];
    	char pin[10];
    	float bal;
    } Account;
    
    Account acct;
    
    void loadAcct(){
    	char strbal[20];
    	
    	FILE *fp;
    	
    	fp = fp = fopen("/acctinfo.txt", "r+");
    	
    	if (fp != NULL) {
    		while(fgets(acct.name, 60, fp) && 3 == fscanf(fp,  "%19s%9s%f", acct.num, acct.pin, &acct.bal)) {
    			printf("%s\n%s\n%s\n%f\n", acct.name, acct.num, acct.pin, acct.bal);
    		}
    	} else {
    		printf("Account info not found.");
    	}
    
    	fclose(fp);
    	getch();
    }
    Last edited by riechan; July 30th, 2013 at 09:56 AM.

  5. #20
    Join Date
    Apr 1999
    Posts
    27,449

    Re: Assigning a value to struct variables?

    Quote Originally Posted by riechan View Post
    I need to get the exact value since I'll be making computations using it...
    Then you can't use double ot float.

    This has been discussed many times here -- if you want accuracy, you need to use all integers or get a library of code that handles exact math. Doubles and floating point variables are by their very nature, inaccurate.

    http://www.parashift.com/c++-faq/floating-pt-errs.html

    Also, if you're using Turbo C, then the output we get will be different than the output that you will get when it comes to floating point values, since in all likelihood, others are using more modern compilers (Visual Studio or gcc). So comparing what 2kaud gets or laserlight gets in terms of that float variable is not an indicator of whether your program works or not.

    I once had to maintain two bodies of code, one coded with Borland C++, the other with Visual Studio 6.0. The floating point calculations when applied to both compilers produced different numbers in the 4th or 5th decimal place.

    Again, all of this is caused by inaccuracies of float and double. For float, there is no standard way that a compiler can represent that number. It could be IEEE or a home-grown version of characteristic/mantissa representation of that number (and I believe Turbo C even emulates floating point values via software, so that is another wrinkle).


    Regards,

    Paul McKenzie
    Last edited by Paul McKenzie; July 30th, 2013 at 10:26 AM.

  6. #21
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,822

    Re: Assigning a value to struct variables?

    I need to get the exact value since I'll be making computations using it...
    As has been said many times before on these threads, some decimal numbers can't be represented exactly as binary - the same way that 1/3 can't be represented exactly as a decimal. That's one reason why I used the %.2f format in the printf statement. However, consider storing bal as a double rather than a float. On my MSVS this gives a more accurate number representation. Also your fscanf format string is not correct. It will not work if there is more than 1 record in the file. Look at my fscanf format.

    I've changed my program to use double rather than float and I'm now printing the whole balance rather than just 2dp.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #define MAXAMT 999999.99
    
    typedef struct Account{
    	char name[60];
    	char num[20];
    	char pin[10];
    	double bal;
    } Account;
    
    Account acct;
    
    void loadAcct(){
    FILE	*fp;
    	
    	if (fp = fopen("acctinfo.txt", "r+")) {
    		while (fgets(acct.name, 60, fp) && fscanf(fp, "%19s\n%9s\n%lf\n", acct.num, acct.pin, &acct.bal) == 3) {
    			if (char *nl = strrchr(acct.name, '\n')) *nl = 0;
    			printf("%s\n%s\n%s\n%lf\n", acct.name, acct.num, acct.pin, acct.bal);
    		}
    	} else {
    		printf("Account info not found.");
    	}
    
    	fclose(fp);
    	//getch();
    }
    
    int main()
    {
    	loadAcct();
    
    	return 0;
    }
    Using input file data of

    Code:
    Rie Ishida
    1234567890
    123456
    123456.78
    code guru
    1234567890
    987654321
    45.67
    this now produces output of

    Code:
    Rie Ishida
    1234567890
    123456
    123456.780000
    code guru
    1234567890
    987654321
    45.670000
    On your turbo c system, try this program as it stands without changes and see what the output produces with the same data as I've used.
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  7. #22
    Join Date
    Apr 1999
    Posts
    27,449

    Re: Assigning a value to struct variables?

    Quote Originally Posted by 2kaud View Post
    On your turbo c system, try this program as it stands without changes and see what the output produces with the same data as I've used.
    I would also be interested in seeing the results.

    I don't think that Turbo C used IEEE doubles (maybe I'm wrong), but I do remember that their floating point was either emulated, or if you had the 8087 chip, done using that FP coprocessor (which predates the IEEE standard used by Visual Studio / gcc).

    Regards,

    Paul McKenzie

  8. #23
    Join Date
    Jul 2013
    Posts
    30

    Re: Assigning a value to struct variables?

    @2kaud: Just made a couple of changes with the code. I used your test data and the results were all correct, surprisingly:

    Name:  Untitled.png
Views: 907
Size:  44.7 KB

    I'm thinking it's because I used float instead of double? And in this line of code, I was getting a 'Expression syntax' error:

    Code:
    if (char *nl; = strrchr(acct.name, '\n')) *nl = 0;
    So, I changed it up to:

    Code:
    char *nl;
    ...
    if (*nl = strrchr(acct.name, '\n')) {
    *nl = 0;
    }
    And now I'm getting a nonportable pointer conversion/possibly incorrect assignment error. When I use this however:

    Code:
    i = strspn(acct.name, "\n");
    acct.name[strspn(acct.name, "\n")] = '\0';
    i = 0 and the acct.name variable is empty.
    Last edited by riechan; July 30th, 2013 at 12:51 PM.

  9. #24
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,822

    Re: Assigning a value to struct variables?

    if (char *nl; = strrchr(acct.name, '\n')) *nl = 0;
    Sorry. That is c++ syntax. I forgot you're using c. In c++ you can define a variable within the if statement whereas you can't in c.

    You need to use strcspn rather than strspn. strspn returns 0 if the first character of acct.name is not a \n which is not what you want!

    Use this

    Code:
    	while (fgets(acct.name, 60, fp) && fscanf(fp, "%19s\n%9s\n%lf\n", acct.num, acct.pin, &acct.bal) == 3) {
    		acct.name[strcspn(acct.name, "\n")] = 0;
    		printf("%s\n%s\n%s\n%lf\n", acct.name, acct.num, acct.pin, acct.bal);
    	}
    I checked this using a c compiler and it compiles OK and produces the same result as above.

    So, I changed it up to:

    Code:

    char *nl;
    ...
    if (*nl = strrchr(acct.name, '\n')) {
    *nl = 0;
    }

    And now I'm getting a nonportable pointer conversion/possibly incorrect assignment error. When I use this however:
    Thats because strrchr returns a pointer and you are assigning a pointer value to a char!

    nl is a pointer to a memory location in which a char can be stored. *nl refers to the actual char stored at the memory location pointed to by nl. I know this can be confusing!

    You need

    Code:
    char *nl;
    ...
    if (nl = strrchr(acct.name, '\n')) {
        *nl = 0;
    }
    Last edited by 2kaud; July 30th, 2013 at 02:01 PM.
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  10. #25
    Join Date
    Apr 1999
    Posts
    27,449

    Re: Assigning a value to struct variables?

    Quote Originally Posted by riechan View Post
    @2kaud: Just made a couple of changes with the code. I used your test data and the results were all correct, surprisingly:
    You must also do one more thing, and that is to #include all of the appropriate headers that correspond with the functions you're calling.

    For example, did you #include <string.h>? You're calling string functions, but I don't see that #include.

    The reason why it is very important for a 'C' program to #include the headers is that a program can and will run differently if you leave them out. For 'C', if a function is undefined, 'C' defaults the return value to int, and that can be disastrous.

    So next time, please post the headers you have included, since a lot of weird output for a 'C' program stems from not including the neessary header files (There was a thread that went on for days, with the issue being exactly that -- a 'C' program that didn't #include the headers, and the poster couldn't understand why they were getting the wrong output).

    Regards,

    Paul McKenzie

  11. #26
    Join Date
    Jan 2006
    Location
    Singapore
    Posts
    6,765

    Re: Assigning a value to struct variables?

    Quote Originally Posted by 2kaud
    You need to use strcspn rather than strspn. strspn returns 0 if the first character of acct.name is not a \n which is not what you want!
    Yeah, my bad.
    C + C++ Compiler: MinGW port of GCC
    Build + Version Control System: SCons + Bazaar

    Look up a C/C++ Reference and learn How To Ask Questions The Smart Way
    Kindly rate my posts if you found them useful

  12. #27
    Join Date
    Jul 2013
    Posts
    30

    Re: Assigning a value to struct variables?

    I suppose I'll be using long integer for the time being, since floating point numbers have been very erratic. But, I'll revise the data types once I finish coding everything. I'll follow up on you guys with the finished code, I think.

    I have a quick question though, when I tried to assign a value to acct.pin:

    Code:
    acct.pin = pina;
    Both acct.pin and pina are string variables with a length of 10. I got an error: "Lvalue required"? I didn't get that error though when I tried using it with integer variables (acct.bal)
    Last edited by riechan; July 31st, 2013 at 11:51 AM.

  13. #28
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,822

    Re: Assigning a value to struct variables?

    Quote Originally Posted by riechan View Post
    I have a quick question though, when I tried to assign a value to acct.pin:

    Code:
    acct.pin = pina;
    Both acct.pin and pina are string variables with a length of 10. I got an error: "Lvalue required"? I didn't get that error though when I tried using it with integer variables (acct.bal)
    acct.pin is a fixed pointer (determined by the compiler) to a memory location where the data resides. So what you are doing isn't valid as you are trying to change the memory location to which acct.pin points. To copy the data from the char array pointed to by pina to the char array pointed to by acct.pin use

    Code:
    strcpy(acct.pin, pina);
    Note that the memory storage allocated for acct.pin must be at least the number of characters copied from pina (not forgetting the terminating null!) - otherwise a buffer overflow occurs.

    For more info on manipulating char arrays in c, have a look at
    http://www.cplusplus.com/reference/cstring/

    I got an error: "Lvalue required"
    An Lvalue is an expression that can be used on the left of an assignment. In the statement

    Code:
    a = 3;
    a is the Lvalue and 3 is the Rvalue. If this was reversed

    Code:
    3 = a;
    then here 3 is the Lvalue and a is the Rvalue. But 3 cannot be assigned a value so this is an error. In your example, acct.pin would be the Lvalue, but you can't assign to this hence the compiler error. This is why you often find if statements of the form

    Code:
    if (3 == a) ...
    rather than

    Code:
    if (a == 3) ...
    both perform the same test, but if the equality relational operator was mistyped as

    Code:
    if (3 = a) ...
    then this would cause a compiler error as 3 is not a valid Lvalue. But the (probably incorrect) statement

    Code:
    if (a = 3) ...
    is valid syntax and assigns a the value of 3 which is the value of the if condition. The condition is then always non-zero so the if statement always evalutes to true.
    Last edited by 2kaud; July 31st, 2013 at 04:49 PM.
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  14. #29
    Join Date
    Apr 1999
    Posts
    27,449

    Re: Assigning a value to struct variables?

    Quote Originally Posted by riechan View Post
    I have a quick question though, when I tried to assign a value to acct.pin:

    Code:
    acct.pin = pina;
    Both acct.pin and pina are string variables with a length of 10. I got an error: "Lvalue required"? I didn't get that error though when I tried using it with integer variables (acct.bal)
    All 'C' books and materials make it a point that null-terminated char arrays are not the same as simple variables. Since they are arrays, you must use functions to manipulate them. Assignment and comparison of arrays cannot be done in C (and in C++) using "simple" operations such as "=" and "==". You must use the functions defined in <string.h> to manipulate null-terminated strings as one entity (as opposed to a single character at a time).

    So are you using a 'C' book? If so, I suggest you read carefully the chapter on null-terminated char arrays, as that is a foundation of 'C' programming when it comes to strings.

    Regards,

    Paul McKenzie

Page 2 of 2 FirstFirst 12

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured