beginner with programming, how to learn to debug and few C generalquestions

B

bpascal123

Hi,

I am first an accountant and decided to take on programming a few
years ago...
I have been first studying simple algorithms...

Now I have decided to first learn C (i'll give it 600 effective hours -
so btw 1 and 3 years) before going to c++ or perl, or python, java or
php or ruby on rails or vba, i'll see at that time what answers most
my needs either as a professionnal accountant or as a personal project
i'd like to take on... Is there anything specific I could do with a
good knowledge of C only ?

So I have been having a hard time with the basics of pointers (20
hours). I really want to feel ok with this before getting any further.
I haven't looked at functions yet.

Here is a programm I know by heart - from a book - but in this code it
doesn't work althought it is very similar to other versions I have
been "coding" over and over more than 30 times ... and 10 % of the
time, there is a bug very similar to the one below I can solve by
looking carefully at the code or cannot solve if I have looked
carefully at the code. That's why I'd like to learn how to debug.

So far or so early with learning C, I'd like to use this opportunity
to learn how to debug and know about the tools that can help.

I have mainly been programming under Windows Xp DJGPP Dolorie... and I
have found a command : simify (link : http://www.delorie.com/djgpp/v2faq/faq9_3.html
) to help debug.

===O===

FIRST, here is the culprit : (this prg inserts a symbol every 3 digits
if the number includes 4 or more digits)

===O===

#include <stdio.h> /* printf, putchar, gets, puts */
#include <conio.h> /* getche */
#include <stdlib.h> /* atoi */
#include <ctype.h> /* isdigit */
#include <string.h> /* strcpy, strlen */

#define BOOL int

/**********/

main()
{
char buffer[128] ;
char clearbuf[128] ;
char output[172] ;

char * pb = buffer, * pc = clearbuf, * po = output ;

int symbol ;
int i, k ;
int cnt ;

BOOL ok ;

/**********/

printf("\033[2J");
printf("\nCe prog separe...\n");

/**********/

do
{
printf("\nSeparateur :");
symbol = getche() ;

if ( symbol < 32 )
printf("Pas de caractere de control comme separateur !");
if ( isdigit(symbol) )
printf("Pas de chiffre comme separateur !" ) ;
} while ( symbol < 32 || isdigit(symbol) ) ;

/**********/

do
{
ok = 1 ;
printf("\nEntrez un nombre entier positif ");
gets(buffer) ;

cnt = 0 ;

while ( *(buffer + cnt) && ok )
{
if ( !isdigit(*(buffer + cnt) ) )
{
printf("Pas d'entier positif!") ;
ok = 0 ;
}
cnt++;
}
} while ( !ok ) ;

/**********/

if ( cnt > 1 && atoi(buffer) )
{
while ( *pb == '0' )
pb++ ;

while ( *pc++ = *pb++ )
;

strcpy(buffer, clearbuf);
}

/**********/

if ( (cnt = strlen(buffer)) > 3)
{
for ( i = cnt - 1, k = 0, pb = buffer ; i >= 0 ; i--, k++ )
{
po[k] = pb ;

if ( ( (cnt - i) % 3 ) == 0 && i != 0 )
po[++k] = symbol ;
}
po[k] = '\0' ;

for ( i = k - 1 ; i >= 0 ; i-- )
putchar(*(output + i));
}
else
puts(buffer) ;
}

===O===

Running this doesn't work after entering a symbol


NOW the simify cmd says (in an dmp output text file) :

===O===

Entrez un separateur : ;
Entrer un nbr (pas plus de 50 chiffres svp) 434334
Exiting due to signal SIGSEGV
General Protection Fault at eip=00001f9e
eax=00092ca5 ebx=0000029d ecx=0000000d edx=00000001 esi=00000054
edi=00012d74
ebp=00092d48 esp=00092b60 program=C:\DJGPP\ACT43B\PTRS36.EXE
cs: sel=01a7 base=029d0000 limit=0009ffff
ds: sel=01af base=029d0000 limit=0009ffff
es: sel=01af base=029d0000 limit=0009ffff
fs: sel=017f base=0000f860 limit=0000ffff
gs: sel=01bf base=00000000 limit=0010ffff
ss: sel=01af base=029d0000 limit=0009ffff
App stack: [00092d74..00012d74] Exceptn stack: [00012cd4..00010d94]

Call frame traceback EIPs:
0x00001f9e _main+243
0x00003a38 ___crt1_startup+176

C:\DJGPP\act43b>symify ptrs36.exe

C:\DJGPP\act43b>symify -o ptrs36.exe
Invalid option -o - type `symify' for help

C:\DJGPP\act43b>symify -o pbb1.dmp ptrs36.exe


====O====

I don't know if I can use what simify says to find any bug.

=========

Am I using simify right ?

Is my bug tracable ?

What(free) tool in my windows Xp context can I use to debug ?

=========

Thanks in advance ,

Pascal
 
B

BartC

Here is a programm I know by heart - from a book - but in this code it
doesn't work althought it is very similar to other versions I have

symbol = getche() ;
gets(buffer) ;

The book you got this from must be ancient, but at first try the code seems
to work (on my OS).

What's the actual problem?

And the register dump stuff is a waste of time at this level.
 
B

BartC

And the register dump stuff is a waste of time at this level.

Ok perhaps not such a waste as the error is mentioned there:

Entrez un separateur : ;
Entrer un nbr (pas plus de 50 chiffres svp) 434334
Exiting due to signal SIGSEGV

I'll have a closer look.
 
B

bpascal123

Sorry - this one below is not working and I don't understand why as it
looks identical to the one working... ===o===

#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>

#define BOOL int

/***********************************/

main()
{
char buffer[128] ;
char output[172] ;
char clearbuf[128] ;

char * pb = buffer, * pc = clearbuf, * po = output ;

int cnt, symbol ;
int i, k ;

BOOL ok ;

/***********************************/

printf("\033[2J");
printf("\nCe prg permet d'inserer...\n");

/***********************************/

do
{
printf("\nSeparateur :");
symbol = getche() ;

if ( symbol < 32 )
printf("Pas de caractere de control comme separateur !");
if ( isdigit(symbol) )
printf("Pas de chiffre comme separateur !" ) ;
} while ( symbol < 32 || isdigit(symbol) ) ;

/***********************************/

do
{
ok = 1 ;

printf("\nEntrer un nbr (pas plus de 50 chiffres svp) ") ;
gets(buffer) ;

cnt = 0 ;

while ( *(buffer + cnt) && ok )
{
if ( !(isdigit(buffer + cnt)) )
{
printf(" \nCe n'est pas un entier positif !") ;
ok = 0 ;
}
cnt++ ;
}
} while ( !ok ) ;

/***********************************/

if ( cnt > 1 && atoi(buffer) )
{
while ( *pb == '0' )
pb++ ;

while ( *pc++ == *pb++ )
;

strcpy(buffer, clearbuf) ;
}

/***********************************/

if ( (cnt = strlen(buffer)) > 3)
{
for ( i = cnt - 1, k = 0, pb = buffer ; i >= 0 ; i--, k++ )
{
po[k] = pb ;

if ( ((cnt - i ) % 3) == '0' && i != 0 )
po[++k] = symbol ;
}
po[k] = '\0' ;

for ( i = k - 1 ; i >= 0 ; i-- )
putchar(*(output + i) ) ;
}
else
puts(buffer) ;
}
 
B

bpascal123

Sorry - this one below is not working and I don't understand why as
it
looks identical to the one working... ===o===



#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#define BOOL int
/***********************************/
main()
{
char buffer[128] ;
char output[172] ;
char clearbuf[128] ;
char * pb = buffer, * pc = clearbuf, * po = output ;
int cnt, symbol ;
int i, k ;
BOOL ok ;
/***********************************/
printf("\033[2J");
printf("\nCe prg permet d'inserer...\n");
/***********************************/
do
{
printf("\nSeparateur :");
symbol = getche() ;
if ( symbol < 32 )
printf("Pas de caractere de control comme
separateur !");
if ( isdigit(symbol) )
printf("Pas de chiffre comme
separateur !" ) ;
} while ( symbol < 32 || isdigit
(symbol) ) ;
/***********************************/
do
{
ok = 1 ;
printf("\nEntrer un nbr (pas plus de 50 chiffres svp)
") ;
gets(buffer) ;
cnt = 0 ;
while ( *(buffer + cnt) && ok )
{
if ( !(isdigit(buffer + cnt)) )
{
printf(" \nCe n'est pas un entier
positif !") ;
ok = 0 ;
}
cnt++ ;
}
} while ( !ok ) ;
/***********************************/
if ( cnt > 1 && atoi(buffer) )
{
while ( *pb == '0' )
pb++ ;
while ( *pc++ == *pb++ )
;
strcpy(buffer, clearbuf) ;
}
/***********************************/
if ( (cnt = strlen(buffer)) > 3)
{
for ( i = cnt - 1, k = 0, pb = buffer ; i >=
0 ; i--, k++ )
{
po[k] = pb ;
if ( ((cnt - i ) % 3) == '0' && i !=
0 )
po[++k] = symbol ;
}
po[k] = '\0' ;
for ( i = k - 1 ; i >= 0 ; i-- )
putchar(*(output + i) ) ;
}
else
puts(buffer) ;

}
 
B

BartC

Sorry - this one below is not working and I don't understand why as
it
looks identical to the one working... ===o===

I'm confused now, which one was supposed to be working, the first one you
posted? With the error dump?

I would stick with that one since that one worked for me and the others
(which have a couple of blatant errors) don't.

No idea how you would use your simify program to pinpoint the error.

If you get segfault errors on your machine, in this simple program I would
just insert exit(0) at specific points to see near line it occurs at (I'd
also hardcode the values of symbol and buffer to avoid having to reenter
these).

Start just after gets(), and if it's OK then just move the exit(0) a bit
further down (gets() is not a good idea to use but you can worry about
replacing it later).
 
A

Andrew Poelstra

Hi,

I am first an accountant and decided to take on programming a few
years ago...
I have been first studying simple algorithms...

Now I have decided to first learn C (i'll give it 600 effective hours
- so btw 1 and 3 years) before going to c++ or perl, or python, java
or php or ruby on rails or vba, i'll see at that time what answers
most my needs either as a professionnal accountant or as a personal
project
i'd like to take on... Is there anything specific I could do with a
good knowledge of C only ?

So I have been having a hard time with the basics of pointers (20
hours). I really want to feel ok with this before getting any further.
I haven't looked at functions yet.

Here is a programm I know by heart - from a book - but in this code it
doesn't work althought it is very similar to other versions I have
been "coding" over and over more than 30 times ... and 10 % of the
time, there is a bug very similar to the one below I can solve by
looking carefully at the code or cannot solve if I have looked
carefully at the code. That's why I'd like to learn how to debug.

So far or so early with learning C, I'd like to use this opportunity
to learn how to debug and know about the tools that can help.

I have mainly been programming under Windows Xp DJGPP Dolorie... and I
have found a command : simify (link :
http://www.delorie.com/djgpp/v2faq/faq9_3.html ) to help debug.

===O===

FIRST, here is the culprit : (this prg inserts a symbol every 3 digits
if the number includes 4 or more digits)

===O===

#include <stdio.h> /* printf, putchar, gets, puts */
#include <conio.h> /* getche */

<conio.h> is part of your Windows library, not of C. Therefore, your
code is not only outside the scope of this group, but more importantly,
many regulars here will be unable to compile your code. (I for one have
no said:
#include <stdlib.h> /* atoi */
#include <ctype.h> /* isdigit */
#include <string.h> /* strcpy, strlen */

#define BOOL int

/**********/

main()

This should be
int main(void)

Which is clearer and works with the latest standardized version of C.
{
char buffer[128] ;
char clearbuf[128] ;
char output[172] ;

char * pb = buffer, * pc = clearbuf, * po = output ;

int symbol ;
int i, k ;
int cnt ;

BOOL ok ;

/**********/

printf("\033[2J");
printf("\nCe prog separe...\n");

You can use puts() instead of printf(), which saves a fair bit of
overhead and automatically adds the \n to the end of every line.
/**********/

do
{
printf("\nSeparateur :");
symbol = getche() ;

What does this function do? If you need to get a single character, use
getc() or fgetc().
if ( symbol < 32 )
printf("Pas de caractere de control comme separateur !");
if ( isdigit(symbol) )
printf("Pas de chiffre comme separateur !" ) ;
} while ( symbol < 32 || isdigit(symbol) ) ;

/**********/

Please use proper indentation when posting on Usenet.
do
{
ok = 1 ;
printf("\nEntrez un nombre entier positif ");
gets(buffer) ;

Stop right here. NEVER ever EVER use gets(). It is impossible to use
safely, since it does no buffer size checking and therefore is inviting
users to overrun your buffer and run over who-knows-what memory.

Use fgets() instead, which will accept sizeof buffer as an additional
argument, and will check the size of the input.
cnt = 0 ;

while ( *(buffer + cnt) && ok )
{
if ( !isdigit(*(buffer + cnt) ) )
{
printf("Pas d'entier positif!") ;
ok = 0 ;
}
cnt++;
}
} while ( !ok ) ;

/**********/

if ( cnt > 1 && atoi(buffer) )

atoi() is also not recommended since it doesn't fail well if you pass it
invalid input. Use strtol() or strtoul() instead.
{
while ( *pb == '0' )
pb++ ;

while ( *pc++ = *pb++ )
;

strcpy(buffer, clearbuf);
}

/**********/

if ( (cnt = strlen(buffer)) > 3)
{
for ( i = cnt - 1, k = 0, pb = buffer ; i >= 0 ; i--, k++ )

Your spacing is abysmal. Please correct it.
{
po[k] = pb ;

if ( ( (cnt - i) % 3 ) == 0 && i != 0 )
po[++k] = symbol ;
}
po[k] = '\0' ;

for ( i = k - 1 ; i >= 0 ; i-- )
putchar(*(output + i));
}
else
puts(buffer) ;
}


If you fix all of the above problems, it might fix whatever the issue
with your code is. But as it stands, I can neither compile nor read the
posted code. So please correct these things, fix the formatting and
repost if you are still having issues.
 
B

Bill Cunningham

[snip]
if ( cnt > 1 && atoi(buffer) )

....

Many prefer strtol to atoi. atoi returns nothing and strtol can be error
checked. Very good you sure learn quickly. Your better than me and I've been
studying on and off for several years now. But I've never made a point of
pointers til now :)

Bill
 
B

Bill Cunningham

Sorry - this one below is not working and I don't understand why as
it
looks identical to the one working... ===o===



#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#define BOOL int
/***********************************/
main()
{
char buffer[128] ;
char output[172] ;
char clearbuf[128] ;
char * pb = buffer, * pc = clearbuf, * po = output ;
int cnt, symbol ;
int i, k ;
BOOL ok ;
/***********************************/
printf("\033[2J");
printf("\nCe prg permet d'inserer...\n");
/***********************************/
do
{
printf("\nSeparateur :");
symbol = getche() ;
if ( symbol < 32 )
printf("Pas de caractere de control comme
separateur !");
if ( isdigit(symbol) )
printf("Pas de chiffre comme
separateur !" ) ;
} while ( symbol < 32 || isdigit
(symbol) ) ;
/***********************************/
do
{
ok = 1 ;
printf("\nEntrer un nbr (pas plus de 50 chiffres svp)
") ;
gets(buffer) ;
cnt = 0 ;
while ( *(buffer + cnt) && ok )
{
if ( !(isdigit(buffer + cnt)) )
{
printf(" \nCe n'est pas un entier
positif !") ;
ok = 0 ;
}
cnt++ ;
}
} while ( !ok ) ;
/***********************************/
if ( cnt > 1 && atoi(buffer) )
{
while ( *pb == '0' )
pb++ ;
while ( *pc++ == *pb++ )
;
strcpy(buffer, clearbuf) ;
}
/***********************************/
if ( (cnt = strlen(buffer)) > 3)
{
for ( i = cnt - 1, k = 0, pb = buffer ; i >=
0 ; i--, k++ )
{
po[k] = pb ;
if ( ((cnt - i ) % 3) == '0' && i !=
0 )
po[++k] = symbol ;
}
po[k] = '\0' ;
for ( i = k - 1 ; i >= 0 ; i-- )
putchar(*(output + i) ) ;
}
else
puts(buffer) ;

}


Myself personally I would've put exit(EXIT_SUCCESS); for portability
rather than exit(0);

Bill
 
A

Andrew Poelstra

Bill said:
Myself personally I would've put exit(EXIT_SUCCESS); for
portability
rather than exit(0);

0 and EXIT_SUCCESS are both portable across all C implementations.
 
B

Ben Bacarisse

I am first an accountant and decided to take on programming a few
years ago...
I have been first studying simple algorithms...

Now I have decided to first learn C (i'll give it 600 effective hours -
so btw 1 and 3 years) before going to c++ or perl, or python, java or
php or ruby on rails or vba, i'll see at that time what answers most
my needs either as a professionnal accountant or as a personal project
i'd like to take on... Is there anything specific I could do with a
good knowledge of C only ?

So I have been having a hard time with the basics of pointers (20
hours). I really want to feel ok with this before getting any further.
I haven't looked at functions yet.

You've had some advice already but I'd like to add something very
general. "Putting off" functions is a bad idea. They are the key
tool for decomposing problem into simpler problems and for building
complex behaviour from simple behaviour. In short, they are a central
theme in programming and you end up making matters worse by using a
text that delays introducing them.

Learn to write simple functions and then learn how to combine simple
functions. The habit of writing lots of function should stay with you
throughout your programming life.

There are other signs that the book you are using is not a good one.
Have you has a look at "The C Programming Language, 2nd Edition" by
Kernighan and Ritchie?

A few other general tips...

If you find yourself writing "flag" variables (like "ok" in your
program) think again. Experienced programmers use then a lot less the
beginners for reasons I have never fully understood. If you still
want to use one, give it a helpful name than "ok".

In C, *(output + i) is the same as output. You use both forms in
your program but the second is almost always clearer.
 
B

Beej Jorgensen

So I have been having a hard time with the basics of pointers (20
hours).

Pointers are what plague beginning C programmers more than anything
else, so you're in good company.

-Beej
 
A

Andrew Poelstra

Bill said:
I see I didn't know that. But what about exit(1); and
exit(EXIT_FAILURE); ?

Bill

The first is non-portable; the second is portable;

The only three return values guaranteed to be portable across all C
implementations are 0, EXIT_SUCCESS and EXIT_FAILURE.
 
B

BartC

What(free) tool in my windows Xp context can I use to debug ?

Under Windows there is a choice of much more up-to-date compilers to use,
for example gcc (as mingw), lcc-win32, and DMC (digital mars). And they
might have debug systems that are more usable (I wouldn't know).

Using DMC, your program crashed when entering the separator using getche().
Changing this to getch() (and printing symbol to the screen) seemed to fix
that. Maybe your djp-whatever compiler has the same problem.
 
G

Guest

Under Windows there is a choice of much more up-to-date compilers to use,
for example gcc (as mingw), lcc-win32, and DMC (digital mars).

also Microsoft's Visual C++ Express. It's free, and despite the name,
can be coerced into being a C compiler
And they
might have debug systems that are more usable (I wouldn't know).

VCC has a fine debugger (Idon't know what "simify" has)
 
G

Guest

You've had some advice already but I'd like to add something very
general.  "Putting off" functions is a bad idea.  They are the key
tool for decomposing problem into simpler problems and for building
complex behaviour from simple behaviour.  In short, they are a central
theme in programming and you end up making matters worse by using a
text that delays introducing them.

there are plenty of languages without pointers and, I'd argue, none
without functions. I don't classify it as a programming language if
it
doesn't have functions!

Functions are way of breaking problems down into sub-problems.
Of using ready built solutions (by you or someone else).

We use them in every day life. "drizzle the olive oil", "knit one",
"remove the cover plate", "goto the airport", "select print".

Functional decomposition is what makes life bearable.

Learn to write simple functions and then learn how to combine simple
functions.  The habit of writing lots of function should stay with you
throughout your programming life.

There are other signs that the book you are using is not a good one.
Have you has a look at "The C Programming Language, 2nd Edition" by
Kernighan and Ritchie?

You *really* should.

A few other general tips...

If you find yourself writing "flag" variables (like "ok" in your
program) think again.  Experienced programmers use then a lot less the
beginners for reasons I have never fully understood.

Its to do with Span of Control matching Scope of Control
if I remember my Constantine and Yourdon correctly.

:)

 If you still
want to use one, give it a helpful name than "ok".

In C, *(output + i) is the same as output.  You use both forms in
your program but the second is almost always clearer.
 
C

Chris Dollin

there are plenty of languages without pointers and, I'd argue, none
without functions.

Prolog (it has relations) and more generally rule-based languages.
(Rules are not functions.) Early BASICs. Assembler. Does COBOL have
functions?
I don't classify it as a programming language if
it doesn't have functions!

Well, maybe. (I don't classify it as a /proper/ programming language
unless it as /first-class/ functions.)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Staff online

Members online

Forum statistics

Threads
473,767
Messages
2,569,571
Members
45,045
Latest member
DRCM

Latest Threads

Top