Go Premium for a chance to win a PS4. Enter to Win

x
?
Solved

Problem comparing struct's record

Posted on 2004-10-27
13
Medium Priority
?
416 Views
Last Modified: 2010-04-15
Hi all, I need to compare 2 records from 2 different structs and would like to know if its possible and if yes, how to do it. I think I've heard you could do it as long as the two struct were define identically...

The problem occurs because I need to format the text to write in a new file. I've sort the informations and now if some item (books in my case) have the same vakue (the same subject in my case), I need to print this information once only. Here's how I thought it could be made. I also tried using the funnction strcmp but it didn't worked.

// We go throught all the books we created
for( i = 0; i < num_books - 1; ++i )
                // This is where I need to format
            if(i>0 && books[i].subject==books[i--].subject)
            {
                        // We print onyl the author's name because the subject is identical
                  fprintf(file_out, "\t\t %s\n", books[i].autor);
            }
            else
            {
                        // We print both the subject and author's name, it's a new subject category
                  fprintf(file_out, "%s\t %s\t\n", books[i].subject, books[i].autor);
            }
    fprintf(file_out, "\n" );

Also I'd like to know if there's a better way to format the text going in a file, with columns always at the same place, etc.

SUBJECT                             AUTHOR
Computers                          Smith, Jim
                                          Hopkin, Marc
                                          Moore, Jack
Graphic Animation                Black, Tim
                                          James, Martin
Historical Demography 1.0    Young, Mike
Organic science                   Walters, Jennifer
X                                        Lane, Rick
 ...


Thanks all,
Frank
0
Comment
Question by:The_Kingpin08
  • 3
  • 3
  • 2
  • +3
13 Comments
 
LVL 16

Assisted Solution

by:PaulCaswell
PaulCaswell earned 200 total points
ID: 12423206
>>I also tried using the function strcmp but it didn't worked.
The strcmp method is the correct way to go. How did you do it and what didnt work.

>>books[i].subject==books[i--].subject
1. This compares the addresses of the two items, not their contents so it will almost always return false.
2. Using ...[i--] will not work for two reasons, a. 'i' will not be decremented untill AFTER the comparison and b. I suspect its not i-- you want, its i-1.

Try:
          if(i>0 && strcmp(books[i].subject,books[i-1].subject) == 0)

Paul

0
 
LVL 16

Expert Comment

by:PaulCaswell
ID: 12423234
P.S.

It is more usual to use:

for( i = 0; i < num_books - 1; i++ )

as the effect of:

for( i = 0; i < num_books - 1; ++i )

can be visually ambiguous and open to misinterpretation by both readers and compilers.

Paul
0
 
LVL 46

Expert Comment

by:Kent Olsen
ID: 12423238
Hi The_Kingpin08,

You can compare two structures that are based on the same definition, but there are a couple of things to be considered.

typedef struct
{
  int    SomeInt;
  char SomeName[40];
} MyStruct_t;

MyStruct_t *Struct1;
MyStruct_t *Struct2;

Assuming that the two structures are properly allocated, you can compare them with memcmp().

if (memcmp (Struct1, Struct2, sizeof (MyStruct_t)))
  /* Compare failed  */

This should give you a valid test 100% of the time.  However, modifying the structure slightly may cause hard-to-find compare problems.

typedef struct
{
  char SomeInt;
  char SomeName[40];
} MyStruct_t;

In this case, the comparison might result in false failures.  By default, C aligns data on word boundaries.  This means that there are some number of unused bytes between SomeInt and SomeName.  If the structure wasn't initialized to a known value when the memory was allocated, you have no way of knowing what is in this "dark area".  It is usually whatever was in this block of memory the last time that it was assigned, which means it must be considered to be "random".

Allocating the memory for the structure with calloc() will solve this as the function initialized the entire structure to zero.

But there is still another gotcha.

typedef struct
{
  int    SomeInt;
  char *SomeName;
} MyStruct_t;


SomeName is a pointer within the structure.  It's quite possible that SomeName in one structure points to a string that is identical to the string being pointed to in another structure.  Yet a compison test of the structures will fail because they point to different addresses.  If your testing for exactness, you want the test to fail.  But if your testing whether the two structures contain {1, "Johnson"} you probably want the test to return SUCCESS.


In short, it's a dangerous kind of test that should be performed ONLY when certain, specific, conditions and needs are met.

Kent
0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
LVL 5

Accepted Solution

by:
van_dy earned 200 total points
ID: 12423350
>>Also I'd like to know if there's a better way to format the text going in a file, with columns always at the same place, etc.

try fprintf(FP, "%-30s %-20s\n", bookname, authorname);

FP -> points to the file your out put is going.

van_dy
0
 
LVL 16

Expert Comment

by:PaulCaswell
ID: 12423352
>>Also I'd like to know if there's a better way to format the text going in a file, with columns always at the same place, etc.
Try saving it in CSV format! Then the results can be imported into databases or spreadsheets.

Or you could try:

          // Print subject on first line or when it changes.
          int printSubject = (i==0) || (strcmp(books[i].subject,books[i-1].subject) != 0);
          // Do the print.
          fprintf ( file_out, "%20.20s%20.20s\n", printSubject?books[i].subject:"", books[i].autor );

I've chosen 20 as a reasonable column width. You can chose any other.

Paul
0
 
LVL 55

Expert Comment

by:Jaime Olivares
ID: 12423422
Disagree with Kdo:

>You can compare two structures that are based on the same definition, but there are a couple of things to be considered.
>typedef struct {
>  int    SomeInt;
>  char SomeName[40];
>} MyStruct_t;
>MyStruct_t *Struct1;
>MyStruct_t *Struct2;
>Assuming that the two structures are properly allocated, you can compare them with memcmp().
>if (memcmp (Struct1, Struct2, sizeof (MyStruct_t)))
>  /* Compare failed  */
>This should give you a valid test 100% of the time.  However, modifying the structure slightly may cause hard-to-find compare problems.

This won't ensure a correct comparison because of char array nature

Even if SomeName is loaded with the same string, let's say "John Doe", which occupies 8 characters plus null character, remaining 31 character will have garbage because them are not used, so comparison could fail if both "garbages" are not the same.
0
 
LVL 55

Expert Comment

by:Jaime Olivares
ID: 12423436
In those cases (where character arrays are present) you have to build your own comparison function with member by member individual comparisons.
0
 
LVL 22

Expert Comment

by:grg99
ID: 12423683
In some very special cases you can compare structs by comparing their memory images, but there are MANY MANY gotchas:

(1)  Some structs have hidden padding bytes that may have random garbage in them, thereby failing a strict byte by byte comparison.

(2)  Any fields that are pointers, sometimes you do want to compare the pointers values (when comparing for very strict type  identity), sometimes you want to compare what they point to, or maybe several levels down in indirection from that.  A simple byte compare won't and can't do this.

(3)  Some fields you may want to compare in a case-independent fashion.  For instance a subject name may work better compared case-insensitive, while a password field is (usually) case sensitive.

(4)  In some cases you may want to compare the numeric values for equality, or "close" equality, even though they may be radically different formats, like some left justified, space filled, or right justified, leading zeroes, or some with leading plus signs.  A simple structure compare won't work for these either.

(5)  You may want to comapre dates for equality, when they may be written in one of many formats: 10-Jan-2001, 01/10/01, 10/1/1, 10/01/2001, and many others.  

--------------------------------
The cleanest way might be to write a structure comparision function that handles each field in its own way:

a rough example:

int MyStructCompare( MyStruct A, MyStruct B )
{
    int Ans;
    Ans = strnocasecmp( A->Name, B->Name );
   if( Ans == 0 ) {
         Ans = strdatecmp( A->SellDate, B->SellDate );
          if( Ans == 0 )  Ans = IntCmp( A->Age, B->Age, 5 )
   }
   return( Ans )
}
... where strnocasecmp() does a case-independent compare (ignoring leading and trailing blanks too)
.... where strdatecmp() accepts a variery of date styles
.... where IntCmp() compares strings for integer nearness, allowing for leading zeroes and spaces and signs
0
 

Author Comment

by:The_Kingpin08
ID: 12424088
Ok thanks  all for the quick answers.

BTW is there a way to force my date into a certain format  when printing in the file ?

Like if my date is 1900-1-1  to print 1900-01-01 instead ?

Thanks againn,

Frank
0
 
LVL 5

Expert Comment

by:van_dy
ID: 12424206
     printf((m > 9)?"%d-%d\n": "%d-0%d-", y, m);           //y = year, m = month, d = day.. if that is how u mean
      printf((d > 9)?"%d\n": "0%d\n", d);
0
 
LVL 46

Assisted Solution

by:Kent Olsen
Kent Olsen earned 100 total points
ID: 12424260
Hi Frank (At last -- a REAL name!)

This is almost the same question that you had yesterday on reformatting dates.

printf ("%04d/%02d/%02d", Year, Month, Day);


Kent
0
 

Author Comment

by:The_Kingpin08
ID: 12424301
Yes thanks Kent, it workd perfectly yesterday except sometimes the 0 didn't appeared. Gonna try this directly in the print instead.

BTW didn't I posted my name before ? ;)

Frank
0
 
LVL 46

Expert Comment

by:Kent Olsen
ID: 12424329

Hi Frank,

You need the leading '0's in the format string to force leading zeros in the output.


Kent
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

An Outlet in Cocoa is a persistent reference to a GUI control; it connects a property (a variable) to a control.  For example, it is common to create an Outlet for the text field GUI control and change the text that appears in this field via that Ou…
This tutorial is posted by Aaron Wojnowski, administrator at SDKExpert.net.  To view more iPhone tutorials, visit www.sdkexpert.net. This is a very simple tutorial on finding the user's current location easily. In this tutorial, you will learn ho…
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use nested-loops in the C programming language.
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use while-loops in the C programming language.
Suggested Courses

916 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question