LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Distributions > Slackware
User Name
Password
Slackware This Forum is for the discussion of Slackware Linux.

Notices


Reply
  Search this Thread
Old 11-29-2013, 01:43 AM   #16
re_nelson
Member
 
Registered: Oct 2011
Location: Texas, USA
Distribution: LFS-SVN, Gentoo~amd64, CentOS-7, Slackware64-current, FreeBSD-11.1, Arch
Posts: 229

Rep: Reputation: Disabled

Quote:
Originally Posted by aaditya View Post
Ah, I understand. I will use it (-ansi -pedantic) now onwards
Now if you really want to get a full measure of the GCC diagnostics, here's a recommended set of flags to turn up the warnings full blast. This is what I use in production code:

Code:
gcc -ansi -pedantic -Wall -Wextra -Wconversion -Wstrict-overflow -Wformat=2
I well recall when first allowed the compiler to nitpick my code many, many, many years ago. It was a humbling experience since I had been getting away with a lot of questionable things for a long time. I buckled down and took the attitude that the compiler was trying to help me and then cleaned up a lot of junk in my code. Nowadays, even the simplest toy program that I write has to pass that gauntlet of GCC (or clang) warnings.

Obviously logic errors aren't detected but much that is potentially suspect is caught by letting the compiler point out deficiencies at the source code level.
 
1 members found this post helpful.
Old 11-29-2013, 02:17 AM   #17
aaditya
Member
 
Registered: Oct 2013
Location: India
Distribution: Slackware
Posts: 272

Original Poster
Blog Entries: 2

Rep: Reputation: 85
Quote:
Originally Posted by re_nelson View Post
Now if you really want to get a full measure of the GCC diagnostics, here's a recommended set of flags to turn up the warnings full blast. This is what I use in production code:

Code:
gcc -ansi -pedantic -Wall -Wextra -Wconversion -Wstrict-overflow -Wformat=2
I well recall when first allowed the compiler to nitpick my code many, many, many years ago. It was a humbling experience since I had been getting away with a lot of questionable things for a long time. I buckled down and took the attitude that the compiler was trying to help me and then cleaned up a lot of junk in my code. Nowadays, even the simplest toy program that I write has to pass that gauntlet of GCC (or clang) warnings.

Obviously logic errors aren't detected but much that is potentially suspect is caught by letting the compiler point out deficiencies at the source code level.
Ah, sorry, I meant that I would use int main() instead of void main()

Using just the -ansi -pedantic options that you earlier described, I seemed to get a lot of warnings, and even more when using all the flags you mentioned!

I have attached the error pastes, I will have a look at them as I can
errors
errors-all
diff-between-flags
 
Old 11-29-2013, 02:34 AM   #18
re_nelson
Member
 
Registered: Oct 2011
Location: Texas, USA
Distribution: LFS-SVN, Gentoo~amd64, CentOS-7, Slackware64-current, FreeBSD-11.1, Arch
Posts: 229

Rep: Reputation: Disabled
Quote:
Originally Posted by aaditya View Post
Using just the -ansi -pedantic options that you earlier described, I seemed to get a lot of warnings, and even more when using all the flags you mentioned!

I have attached the error pastes, I will have a look at them as I can
errors
errors-all
diff-between-flags
We're probably in grave danger of a bad case of topic drift since this isn't Slackware-specific (although Slackware is an excellent platform for learning C since all of the tools and libraries are all there out of the box). So, I'll wrap up my participation in this thread by hoping you have fun tracking down all of the nitpicky compiler warnings.

Although it's initially quite a chore, it will pay off because your code will be clean and solid. Although it may not seem that way at this point, the compiler is your friend! Yes, an annoying, pedantic friend but still a friend.
 
Old 11-29-2013, 02:39 AM   #19
jtsn
Member
 
Registered: Sep 2011
Posts: 925

Rep: Reputation: 483Reputation: 483Reputation: 483Reputation: 483Reputation: 483
Quote:
Originally Posted by re_nelson View Post
It's a violation of the C standard to use the void main() signature. The fact that it "works" on most implementations is not relevant in terms of standard conformance. It comes at no cost and is the right thing to do.
If the function signature between caller and callee differs, you simply get undefined behavior (means unreliable programs just working by accident, like systemd). The reason why a C compiler doesn't complain is because of its default assumption that the programmer knows what he's doing.

There are (embedded) implementations using void main() and there void main() is the (only) correct thing.

But our the standard C library does a call to a main() function returning an int, because int is the default return type of C. You may get away with it, if your caller isn't using the return value, but the C library actually is using the return value of main() to call _exit() with it. (So calling exit() yourself is just a waste of time, returning from main() is just fine).
 
1 members found this post helpful.
Old 11-29-2013, 03:16 AM   #20
jtsn
Member
 
Registered: Sep 2011
Posts: 925

Rep: Reputation: 483Reputation: 483Reputation: 483Reputation: 483Reputation: 483
Some notes on the code:
Quote:
Code:
        //Extract the year,month,day components from the date

        char yi[5],yf[5],mi[3],mf[3],di[3],df[3];        //size+1 for null character at the end
        
        strncpy (yi, argv[1], 4);
        strncpy (mi, argv[1]+5, 2);
        strncpy (di, argv[1]+8, 3);
        
        strncpy (yf, argv[2], 4);
        strncpy (mf, argv[2]+5, 2);
        strncpy (df, argv[2]+8, 3);

        yi[4]='\0';        //insert null character at the end
        mi[2]='\0';        
        yf[4]='\0';     //insert null character at the end
        mf[2]='\0';
Learning to do string handling correct in C is very hard. Seeing someone calling strcpy/strncpy() numerous times is a sure sign, that something is done wrong.

What is argv[1]+5 actually doing? Well, it's reading beyond the end of the string from invalid memory, if I just call your program with "dur 0 0" for example.

So what can you do to learn who to do C string handling right?

Remove the #include <string.h> and implement the thing without using any string functions from the C library. It's possible. Learn how to work with char arrays and string pointers first, how stop at the end of the string and how to validate the input to your program. Use the string library later, when you know exactly, what's going on.

Don't declare functions inside header files (to_int.h) and don't use the GPLv3 preamble on trivial functions like to_int(), they don't reach the threshold of originality for receiving copyright anyway. Beside that, atoi() from the C standard library is doing exactly the same thing. Writing good C programs without knowing the standard library is not possible...

One the final question: What exactly has this thread to do with Slackware at all?
 
1 members found this post helpful.
Old 11-29-2013, 03:53 AM   #21
aaditya
Member
 
Registered: Oct 2013
Location: India
Distribution: Slackware
Posts: 272

Original Poster
Blog Entries: 2

Rep: Reputation: 85
Quote:
Originally Posted by jtsn View Post
Some notes on the code:

Learning to do string handling correct in C is very hard. Seeing someone calling strcpy/strncpy() numerous times is a sure sign, that something is done wrong.

What is argv[1]+5 actually doing? Well, it's reading beyond the end of the string from invalid memory, if I just call your program with "dur 0 0" for example.

So what can you do to learn who to do C string handling right?

Remove the #include <string.h> and implement the thing without using any string functions from the C library. It's possible. Learn how to work with char arrays and string pointers first, how stop at the end of the string and how to validate the input to your program. Use the string library later, when you know exactly, what's going on.

Don't declare functions inside header files (to_int.h) and don't use the GPLv3 preamble on trivial functions like to_int(), they don't reach the threshold of originality for receiving copyright anyway. Beside that, atoi() from the C standard library is doing exactly the same thing. Writing good C programs without knowing the standard library is not possible...

One the final question: What exactly has this thread to do with Slackware at all?
Ah, sorry I am not very well versed in C.

I had made this program to be called with the correct arguments by an external program, and not by the user, and hence skipped checking for invalid input
(I also mention this in a comment)

Will try to implement this without the library function <string.h>, perhaps add a function in to_int.h to do this.

Will read more on what header files are and what they contain, and accordingly change to_int.h to to_int.c
I used the GPL because I made this on my own, so I think I can use it (didnt know about the atoi() function, I will try to acquaint myself with the standard library functions, thx)

I posted this here becasue-
1.I use Slackware and wanted to share it with Slackware users.
2.I think that many Slackware users are programmers, and I thought that if I posted here, maybe some of them will give feedback (thank you)
3.I list 2 applications for this program which can be used on Slackware.

Thanks

Last edited by aaditya; 11-29-2013 at 04:48 AM.
 
Old 11-29-2013, 08:02 AM   #22
tronayne
Senior Member
 
Registered: Oct 2003
Location: Northeastern Michigan, where Carhartt is a Designer Label
Distribution: Slackware 32- & 64-bit Stable
Posts: 3,541

Rep: Reputation: 1065Reputation: 1065Reputation: 1065Reputation: 1065Reputation: 1065Reputation: 1065Reputation: 1065Reputation: 1065
Keep in mind that what julday() is doing is converting a Gregorian calendar date to a fixed "address" in time. Julian Day 0 is -4713-01-01 (BCE), every day since is one "tick" of the Julian Day "clock." Today (2013-11-29) is 2456626, using a different function, caldat():
Code:
julian
2456626
caldat 2456626
Julian Day 2456626: 11/29/2013
The julian program produces today's Julian Day, the caldat program produces the Gregorian calendar date from the Julian Day (it's a check to convert one way then covert the other way to make sure you've got it right). The equations are all given in the Wikipedia article noted above. The piece of the julian program that does the conversion is (using the system clock):
Code:
        /*      get the system time     */
        (void) time (&now);
        /*      make it local time      */
        tm = localtime (&now);
        if (vopt) {
                (void) fprintf (stdout,
                    "%02d%02d.%02d %02d/%02d/%04d %ld\n",
                    tm->tm_hour, tm->tm_min, tm->tm_sec,
                    tm->tm_mon + 1, tm->tm_mday, tm->tm_year + 1900,
                    julday (tm->tm_mon + 1, tm->tm_mday, tm->tm_year + 1900));
        } else {
                (void) fprintf (stdout, "%ld\n",
                    julday (tm->tm_mon + 1, tm->tm_mday, tm->tm_year + 1900));
        }
It simply invokes the same julday() function used in ndays.c, which returns the Julian Day, to do so.

The idea of ndays is that you determine the Julian Day for each of two Gregorian calendar dates and evaluate the difference. As it turns out, I'm 25425 days old as of today (ouch!). Actually, ndays is quite useful in project planning; determine what needs to be done, determine how long it takes to do a given task, put it all together and determine when the project will be complete (Gantt charts and the like). If you have somebody's birth date and you need to know their age, pretty simple (divide ndays by 365.25 and you're pretty close).

Here's caldat.c:
Code:
#include <math.h>
#include <time.h>

#define IGREG   2299161

void    caldat  (time_t julian, int *mm, int *id, int *iyyy)
{
        time_t  ja, jalpha, jb, jc, jd, je;

        if (julian >= IGREG) {
                jalpha = ((float) (julian - 1867216) - 0.25) / 36524.25;
                ja = julian + 1 + jalpha - (time_t) (0.25 * jalpha);
        } else {
                ja = julian;
        }
        jb = ja + 1524;
        jc = 6680.0 + ((float) (jb - 2439870) - 122.1) / 365.25;
        jd = 365 * jc + (0.25 * jc);
        je = (jb - jd) / 30.6001;
        *id = jb - jd - (int) (30.6001 * je);
        *mm = je - 1;
        if (*mm > 12)
                *mm -= 12;
        *iyyy = jc - 4715;
        if (*mm > 2)
                --(*iyyy);
        if (*iyyy <= 0)
                --(*iyyy);
}

#undef  IGREG
Again, see the Wikipedia article to help with understanding the calculations.

Anyway, I hope you find this useful.
 
Old 11-29-2013, 08:20 AM   #23
aaditya
Member
 
Registered: Oct 2013
Location: India
Distribution: Slackware
Posts: 272

Original Poster
Blog Entries: 2

Rep: Reputation: 85
Hehe, thanks again tronayne I think I understand what you are trying to say.
Now I can use ndays and dur to find the difference b/w 2 dates

Btw, the average of your, mine, and re_nelson's ages is 40747 days
 
Old 11-29-2013, 11:52 AM   #24
aaditya
Member
 
Registered: Oct 2013
Location: India
Distribution: Slackware
Posts: 272

Original Poster
Blog Entries: 2

Rep: Reputation: 85
Ok,taking suggestions from jtsn I changed the header file (now its stringfunc.h, and doesnt include <string.h>) and rewrote all the functions that I needed

Now its doing some error handling, but not all, which I dont understand

Code:
./dur 0 0                   
Invalid arguments. The arguments are like yyyy-mm-dd yyyy-mm-dd where the first is the initial date and the next is the final date.

./dur 00 02
Invalid arguments. The arguments are like yyyy-mm-dd yyyy-mm-dd where the first is the initial date and the next is the final date.

./dur 00 022
Invalid arguments. The arguments are like yyyy-mm-dd yyyy-mm-dd where the first is the initial date and the next is the final date.

./dur 00 0223
Segmentation fault

 ./dur 000 0223
Segmentation fault

./dur 2013-01-01 `date +%F`
 332 day(s)
I also tried to implement re_nelson's suggestion of correcting the code which the compiler thinks is incorrect (didnt get all the way though yet)

Interested parties can take a look at the code.
https://github.com/aadityabagga/dur

Edit-
Mods if you feel this is getting off-topic, you can split this topic.

Last edited by aaditya; 11-29-2013 at 12:29 PM.
 
Old 11-29-2013, 12:37 PM   #25
Martinus2u
Member
 
Registered: Apr 2010
Distribution: Slackware
Posts: 497

Rep: Reputation: 119Reputation: 119
Quote:
Originally Posted by aaditya View Post
It took some time and effort (its 200 lines of code + testing for different cases!(also available)), but finally I made it!
I hate doing this to you, but the core logic can be done in 3 lines of code kudos for the effort though.

cf. http://alcor.concordia.ca/~gpkatch/
 
1 members found this post helpful.
Old 11-29-2013, 12:47 PM   #26
aaditya
Member
 
Registered: Oct 2013
Location: India
Distribution: Slackware
Posts: 272

Original Poster
Blog Entries: 2

Rep: Reputation: 85
Quote:
Originally Posted by Martinus2u View Post
I hate doing this to you, but the core logic can be done in 3 lines of code kudos for the effort though.

cf. http://alcor.concordia.ca/~gpkatch/
Ah, Thank You
Didnt know about this before
I think that this implementation uses the modified Julian day method mentioned by tronayne in this thread.
 
Old 11-29-2013, 09:57 PM   #27
jtsn
Member
 
Registered: Sep 2011
Posts: 925

Rep: Reputation: 483Reputation: 483Reputation: 483Reputation: 483Reputation: 483
Quote:
Originally Posted by aaditya View Post
Ok,taking suggestions from jtsn I changed the header file (now its stringfunc.h, and doesnt include <string.h>) and rewrote all the functions that I needed
Function definitions still don't belong to header files. the go into .c files, header files only contain #defines of CONSTANTs, data types and extern declarations (aka function prototypes).

If think, you first need a good book on C, because whatever study material you currently using, it is completely worthless. You didn't understand what a "header guard" does...

Now, instead of implementing the date extraction without calling any string functions (which is possible), you implemented some string functions yourself. Which is a good beginner's exercise, too. So lets have a look at your code:

Code:
unsigned int length(char* string)
{
        int len=0;

        char c=*string;                /*The first character of the string*/
        while(c!='\0')
        {
                len=len+1;        /*len incremented on reading each character*/
                c=*(string+len);        /*now point to next character*/
        }
        
        return len;
}
So who does teach you this sort of over-complicated stuff? How could a standard library function like strlen() be implemented? Like this:

Code:
size_t strlen(char *s)
{
     size_t len = 0;

     while(*s++)
          len++;

     return len;
}
Now try to understand that code and how exactly it works. (It does exactly the same thing as your "length()" function). You don't learn C by writing code, you learn it by reading and understanding code.

As an exercise try to break it down to one line using a single for() statement.

Some notes on the remaining code: You never cast void* pointers in C (the return value of malloc() ), because that disables type checking. You always check the return value of malloc(), because if memory allocation fails, it returns NULL.

It's a good practice to leave memory allocation to the caller of the function and don't return pointers on newly allocated memory. C is not Java, you don't have garbage collection, so you have to free() everything, what you allocate with malloc()...

Quote:
Mods if you feel this is getting off-topic, you can split this topic.
I think this thread should go into the "Programming" LQ forum. And of course, it can't replace a good lecture on C programming.
 
2 members found this post helpful.
Old 11-30-2013, 12:25 AM   #28
aaditya
Member
 
Registered: Oct 2013
Location: India
Distribution: Slackware
Posts: 272

Original Poster
Blog Entries: 2

Rep: Reputation: 85
Thank you for your advice and time I will try to address your points one by one.

Ok, functions should go in .c files, I mistakenly thought that header files contained functions, becuase I include <stdio.h> to use printf
I checked stdio.h in /usr/include and it doesnt have any functions.

I read about header guards yesterday on Wikipedia after searching for header files in C.

Understood what your function is doing. Here is the exercise with the for loop-
Code:
size_t strlenx(char *s)
{
	size_t len=0;

	for(;*s++;len++);

	return len;

}
Will read more on malloc().
Understood your point about memory allocation being left to the caller function.

Will try to improve the code.
Thanks
 
Old 11-30-2013, 08:14 AM   #29
tronayne
Senior Member
 
Registered: Oct 2003
Location: Northeastern Michigan, where Carhartt is a Designer Label
Distribution: Slackware 32- & 64-bit Stable
Posts: 3,541

Rep: Reputation: 1065Reputation: 1065Reputation: 1065Reputation: 1065Reputation: 1065Reputation: 1065Reputation: 1065Reputation: 1065
I humbly suggest that you may benefit from a book, perhaps two.

At least get a copy of Brian W. Kernighan, Dennis M. Ritchie The C Programming Language (2nd ed: Englewood Cliffs, New Jersey: Prencitce-Hall Inc., 1978, ISBN 0-13-110362-8) from Amazon.com or whatever source you have available to you. It's the "bible," written by the guys that invented C and written in an easy-to-understand way that explains everything clearly. Invaluable on your bookshelf.

I highly recommend Stephen G. Kochan Programming in C (3rd ed.: New York: Sams Publishing, 2004, ISBN 978-0672326660). This is a how-to, why-to, what-to-do that is written clearly, full of useful examples, well worth your time and an excellent learning tool.

Hope this helps some.
 
2 members found this post helpful.
Old 11-30-2013, 10:41 AM   #30
aaditya
Member
 
Registered: Oct 2013
Location: India
Distribution: Slackware
Posts: 272

Original Poster
Blog Entries: 2

Rep: Reputation: 85
Thanks tronayne
I already have the K&R C (ebook,havent read it all though)
I have studied from the the 2nd one as well (dont have it though)
Edit-2nd one also downloaded.
Plus I have in hard copy, http://www.amazon.com/Let-Us-Yashava.../dp/8176566217 (with solutions)
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
A program to compute number of days between two dates? stf92 Slackware 72 04-26-2013 10:13 PM
program to calculate dates for scripts Skaperen Programming 6 04-12-2012 02:09 AM
shell script to find the difference betwwn two file and place the difference to other kittunot4u Linux - General 3 07-19-2010 04:26 AM
Calculating the difference between two dates mikejreading Linux - Newbie 1 05-08-2009 09:22 AM
Difference between two dates Uday123 Programming 5 02-23-2009 06:26 AM

LinuxQuestions.org > Forums > Linux Forums > Linux - Distributions > Slackware

All times are GMT -5. The time now is 08:33 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration