help a beginner : code not working

M

Moi

Moi said:
For ( i = 0 ; i != isspace(T1d) ; i++ )
cnt1++ ;

'for' is not capitalized (and comparing 'i' to the return value of
isspace makes little sense).


And: what is the intended *purpose* of this program fragment ?


I would guess that the intention is to count the number of spaces in a
string.


That could account for the first loop.
But the second and third loop make no sense to me.

AvK
 
B

bpascal123

:( I feel so sad of being so worthless with C at this time. At least,
it's a challenge not about what i get to learn but about how worthless
i can feel at some point...

This block is part of a small application tutorial from a website i
decided to take on. Among the question, one is to have a sentence
reversed ie : "i think yes" => "yes think i".

At the stage this application is, following the author's tutorial, he
can only expects the use of basic string functions (isspace might not
even be part of the answer), basic loops, arrays and that's about it.
It isn't yet question of pointers and functions.

My idea is to start from a sentence in memory, get the number of
spaces in it and initiate a multidimension array from it char Array[L]
[C], i should get L from the number of blank spaces returned by
isspace and C from the number of characteres (letters) between blank
spaces.

I would then print the multidimension array down from the last line
(keeping words in order) up to the first line.

If I'm able to implement this basic thing, i'd like to recode this
code from a sentence entered by the user.

Thx
 
B

Ben Bacarisse

:( I feel so sad of being so worthless with C at this time. At least,
it's a challenge not about what i get to learn but about how worthless
i can feel at some point...

This is one of the problems with C. Progress can be slow unless you
have a fair amount of experience of programming.
This block is part of a small application tutorial from a website i
decided to take on. Among the question, one is to have a sentence
reversed ie : "i think yes" => "yes think i".

At the stage this application is, following the author's tutorial, he
can only expects the use of basic string functions (isspace might not
even be part of the answer), basic loops, arrays and that's about it.
It isn't yet question of pointers and functions.

Then it is a poor tutorial, I think (link?). The exercises should
have reasonable solutions using what has been learnt and, like almost
all programs, you should use functions and, in C, when you mix arrays
(like string) and functions, you get pointers. Don't let that worry
you. You have used functions and pointers already so do this using
everything your know.
My idea is to start from a sentence in memory, get the number of
spaces in it and initiate a multidimension array from it char Array[L]
[C], i should get L from the number of blank spaces returned by
isspace and C from the number of characteres (letters) between blank
spaces.

The number of spaces is not the same as the
number of words.

Multidimensional arrays are right pain in C. I would urge you to
consider other options. For example, would it help if you had a
function could reverse a part of a string? What about a function that
can "rotate" a portion of a string? (By this I mean given:

"abc def ghi" start == 0, end == 7

it turns the string into "bc defa ghi".) There are lots of ways to
tackle this, but even an array of pointers to the words would be
simpler than a multidimensional array. I say "even" because you
probably find pointers a little bit intimidating at this stage.
I would then print the multidimension array down from the last line
(keeping words in order) up to the first line.

If you need only to print the result, you don't need to string
anything at all. Could you write a function to find the last word
and, from that information, print it? Could you change that function
or that call so as to find the next-to-last word?

<snip>
 
B

Barry Schwarz

Hi,

I think this code below is working both on linux and windows. A very
few minor changes were needed. Published in 1996 doesn't make this
code so "out of range".


/* Manage 10 strings in an array of pointeurs */

#include <stdio.h> /* printf, gets */
#include <string.h> /* strcmp, strcpy, strlen */
#include <stdlib.h> /* malloc, free, exit */

int main(void)
{
char *list[10] ;
char *temp ;
char buffer[128] ;
int i = 0 ;
int m, n, rep ;

printf("\n\nINITIALISATION OF A LIST\n") ;
printf("\nMaximum of 10 entries in this format :\n") ;
printf("Last name, first name (country)\n") ;

do
{
printf("\nEntry %d : ", i+1 ) ;
fgets(buffer, 128, stdin) ;

if (strcmp(buffer, "0"))
{
if ((list = (char *) malloc(strlen(buffer) + 1)) == NULL )


The cast is worse than superfluous.
{
printf("\nOut of memory.\n") ;
if ( i > 0 )
{
while ( getchar() != '\n') ;
printf("\nDisplay current listing ? (o/n)") ;

if ( rep == 'o' )

The value of rep is indeterminate so this invokes undefined behavior.
break ; /* does break quit the if from if (strcmp(buffer,
"0")) ??? */
No.

}
exit(1) ;

This is not a portable value to return from main.
}
strcpy(list, buffer) ;
i++ ;
}
} while ( i < 10 && strcmp(buffer, "0") ) ;


for ( m = i - 1 ; m > 0 ; m-- )

for ( n = 0 ; n < m ; n++ )
if ( strcmp(list[n], list[n+1]) > 0 ) /* The author wrote list
instead of list[n], could it had been : strcmp( *list, *(list+1) ) ???


While those are syntactically correct they represent different logic.
If he had written *(list+n) and*(list+n+1), it would mean the same as
what your wrote. The expression list as an argument to strcmp without
some kind of dereference operator is a constraint violation.
*/
{
temp = list[n] ;
list[n] = list[n+1] ;
list[n+1] = temp ;
}

if ( i > 0 )
{
printf("\nENTRY LISTING : \n") ;
for ( m = 0 ; m < i ; m++ )
printf("%s\n", list[m] ) ;
}

for ( m = 0 ; m < i ; m++ )
free(list[m]) ;

A return with either 0 or EXIT_SUCCESS would be nice here.
}

Recopied from this book : PC Poche Langage C from G.Willms published
by Micro Application...hope there won't be copyright big issues...

Are you sure you copied it correctly?
 
B

bpascal123

Hi,

I think what is below should work with little modification.

To reply all in one earlier post about this code.

The tutorial this application is from might be light, i can't expect
much from free resources found on the internet but i think it gives a
good approach of basic C and an understanding of algorithms which is
what I'm trying to focus on now before i get to more advanced
programming techniques (pointers...) and other languages... I'd just
like to be able at this stage of learning to implement basic programms
without first using pointers.

If someone can have a quick view. The tutorial for this application
skips the answer for that specific question so i don't have any
references on what to rely. And i'd expect it's possible to revert
words (not letters) in C only using simple loops and non pointers
arrays. I spend 2-3 hours looking for a similar code on the internet
but it seems as Ben says multidimensional arrays a pain in C. While
i'm learning C (for no specific reasons), as an accountant, i'd like
to focus whenever i meet that kind of basic challenges on these since
i think it could help with excel or other spreadsheets applications.

I understand this code here is very, very weak, the sentence must be
part of the code, it then must have a blank space at the end (i
couldn't make isspace to grab each ' ' or '\0'...) and i'm not even
sure if it's the good way to start from.
I think this can be part of one or 2 functions since it performs one
main function (revert words).
In the code below, i'd like to host data from a char unidimensional
array into a 2 dimensional array.

#include <stdio.h>

#include <ctype.h>




int main(void)

{

int L = 0 ; int C = 0 ; /* Lines and Columns of T2d */

char T1d[12] = "I think yes " ;

char T2d[L][C] ; /* T2d should host T1d */



int cnt1 = 0 ; int cnt2 = 0 ; int cnt3 = 0 ;

int i = 0 ; int j = 0 ; int z = 0 ;



while (T1d )

{

if ( isspace(T1d) )

L++;

i++ ;

}



printf("\n\nPour controle : Nombre de lignes : %d \n", L-1) ; /* L
value is wrong b/c of the extra space */



for ( i = 0 ; T1d != ' ' ; i++ )

cnt1++ ;



for ( i = cnt1+1 ; T1d != ' ' ; i++ )

cnt2++ ;


for ( i = cnt1+cnt2+2 ; T1d != ' ' ; i++ )

cnt3++ ;


printf("\nPour controle : nbr de lettres : %d %d %d\n", cnt1, cnt2,
cnt3) ;


C = cnt1 + cnt2 + cnt3 ;

printf("\nPour controle : nbr de colonnes : %d \n\n", C) ;

for ( i = L ; i <= 0 ; i-- )
for ( j = C, z = 12 ; j <= 0 ; j--, z-- )
T2d[j] = T1d[z] ;

for ( i = L ; i = 0 ; i-- )
for ( j = 0 ; j <= C ; j++ )
printf("%s", (T2d[j])) ;


return 0 ;

}
 
M

Morris Keesan

int L = 0 ; int C = 0 ; /* Lines and Columns of T2d */

char T1d[12] = "I think yes " ;

char T2d[L][C] ; /* T2d should host T1d */

L = 0; C = 0; char T2d[L][C]; What are the dimensions of T2d?
 
M

Morris Keesan

L = 0; C = 0;  char T2d[L][C];  What are the dimensions of T2d?

2 dimensions


That's how MANY dimensions there are (rows and columns).
How many rows are there, and how many columns?

To make it simpler:

int foo = 0;
char bar[foo];

What is the size of bar?
 
B

bpascal123

L = 0; C = 0;  char T2d[L][C];  What are the dimensions of T2d?
2 dimensions

That's how MANY dimensions there are (rows and columns).
How many rows are there, and how many columns?

<>
L = 3 ... blank space
C = 5 ... the number of letters in the longest word eg think = 5.
To make it simpler:

int foo = 0;
char bar[foo];

What is the size of bar?

Size of bar should be 2 bits = "" + '\0' .
 
B

Barry Schwarz

Hi,

I think what is below should work with little modification.

You have to be joking. Did you even bother to compile it?
To reply all in one earlier post about this code.

The tutorial this application is from might be light, i can't expect
much from free resources found on the internet but i think it gives a
good approach of basic C and an understanding of algorithms which is

If you tell us where you got it we can warn other people to stay away
from it.
what I'm trying to focus on now before i get to more advanced
programming techniques (pointers...) and other languages... I'd just
like to be able at this stage of learning to implement basic programms
without first using pointers.

Then you better stop using printf.
If someone can have a quick view. The tutorial for this application
skips the answer for that specific question so i don't have any
references on what to rely. And i'd expect it's possible to revert
words (not letters) in C only using simple loops and non pointers
arrays. I spend 2-3 hours looking for a similar code on the internet
but it seems as Ben says multidimensional arrays a pain in C. While
i'm learning C (for no specific reasons), as an accountant, i'd like
to focus whenever i meet that kind of basic challenges on these since
i think it could help with excel or other spreadsheets applications.

I understand this code here is very, very weak, the sentence must be
part of the code, it then must have a blank space at the end (i
couldn't make isspace to grab each ' ' or '\0'...) and i'm not even
sure if it's the good way to start from.
I think this can be part of one or 2 functions since it performs one
main function (revert words).
In the code below, i'd like to host data from a char unidimensional
array into a 2 dimensional array.

#include <stdio.h>

#include <ctype.h>




int main(void)

{

int L = 0 ; int C = 0 ; /* Lines and Columns of T2d */

Would you please fix the line length in your newsreader so that you
don't get a 2 for 1 expansion. I have cleaned up the ones that
follow.
char T1d[12] = "I think yes " ;
char T2d[L][C] ; /* T2d should host T1d */

In C90, this is invalid syntax. In C99 it is a constraint violation.
Even if you compiler accepts it, T2D has 0 elements.
int cnt1 = 0 ; int cnt2 = 0 ; int cnt3 = 0 ;
int i = 0 ; int j = 0 ; int z = 0 ;
while (T1d )
{
if ( isspace(T1d) )
L++;
i++ ;
}
printf("\n\nPour controle : Nombre de lignes : %d \n", L-1) ; /* L
value is wrong b/c of the extra space */


What extra space? What value were you expecting? What value did you
get?
for ( i = 0 ; T1d != ' ' ; i++ )
cnt1++ ;
for ( i = cnt1+1 ; T1d != ' ' ; i++ )
cnt2++ ;
for ( i = cnt1+cnt2+2 ; T1d != ' ' ; i++ )


What will you do if the last word is not followed by a blank.
cnt3++ ;
printf("\nPour controle : nbr de lettres : %d %d %d\n", cnt1, cnt2,
cnt3) ;
C = cnt1 + cnt2 + cnt3 ;
printf("\nPour controle : nbr de colonnes : %d \n\n", C) ;
for ( i = L ; i <= 0 ; i-- )

How many times do expect this loop to run? How often will the second
expression be true?
for ( j = C, z = 12 ; j <= 0 ; j--, z-- )
T2d[j] = T1d[z] ;


Immediate undefined behavior once you fix the for statements so it
actually executes.
for ( i = L ; i = 0 ; i-- )

Can the second expression ever be true.
for ( j = 0 ; j <= C ; j++ )
printf("%s", (T2d[j])) ;


More undefined behavior. Actually multiple instances if that is not
an oxymoron. What type does %s require the corresponding argument to
be? What is the type of T2d[j], ignoring the fact that that
particular element doesn't exist?
 
K

Keith Thompson

Barry Schwarz said:
On Fri, 24 Jul 2009 10:08:18 -0700 (PDT), "(e-mail address removed)"
int L = 0 ; int C = 0 ; /* Lines and Columns of T2d */

Would you please fix the line length in your newsreader so that you
don't get a 2 for 1 expansion. I have cleaned up the ones that
follow.
char T1d[12] = "I think yes " ;
char T2d[L][C] ; /* T2d should host T1d */

In C90, this is invalid syntax. In C99 it is a constraint violation.
Even if you compiler accepts it, T2D has 0 elements.

It's not a constraint violation in C99, it's undefined behavior
(C99 6.7.5.2p5). A C99 compiler isn't required to detect that
L and C will have the value 0.

[...]
 
K

Keith Thompson

L = 0; C = 0;  char T2d[L][C];  What are the dimensions of T2d?
2 dimensions

That's how MANY dimensions there are (rows and columns).
How many rows are there, and how many columns?

<>
L = 3 ... blank space
C = 5 ... the number of letters in the longest word eg think = 5.
[...]

The quoted code clearly initializes L and C to 0. What makes you
think they'll have the value 5? If some code that wasn't shown here
later changes the values of L and C, that doesn't affect T2d.

Given these declarations:

int L = 0;
int C = 0;
char T2d[L][C];

the behavior is undefined. (If it were defined, presumably T2d would
have a size of 0, but C doesn't support 0-sized objects.)
To make it simpler:

int foo = 0;
char bar[foo];

What is the size of bar?

Size of bar should be 2 bits = "" + '\0' .

I assume you mean bits, not bytes.

No, bar is an array object, not a string. Arrays of char can hold any
arbitrary sequence of chars, not just strings. And even without those
mistakes, 2 is incorrect.

The behavior of the above code is undefined. (If it were defined,
sizeof bar would probably be 0.)

Another, even simpler, example:
char arr[1] = { 'x' };

The size of arr is 1 byte. It doesn't contain a string; it contains a
single char with the value 'x'. There is no terminating '\0' (and no
need for a '\0' as long as you don't try to treat it as a string.)

char empty_string = "";

The size of empty_string is 1 byte. It contains a single char with
the value '\0'. It happens to contain a string of length 0.
 
P

Phil Carmody

Keith Thompson said:
char empty_string = "";

The size of empty_string is 1 byte. It contains a single char with
the value '\0'. It happens to contain a string of length 0.

Presumably missing []?

Phil
 
K

Keith Thompson

Phil Carmody said:
Keith Thompson said:
char empty_string = "";

The size of empty_string is 1 byte. It contains a single char with
the value '\0'. It happens to contain a string of length 0.

Presumably missing []?

Whoops, yes.

char empty_string[] = "";
 
B

bpascal123

The value of rep is indeterminate so this invokes undefined behavior.

I must admit that i skipped this line from the book i took the code
from : originally : rep = getche();

But I think getche is part of conio and it's not really popular today
because of standards. I might have replaced it myself with a scanf
function from stdio library. But today on another code, i realized
after 2 or 3 hours scanf is not always working as one would expect.

At the time i wrote down the book's code, i admit i didn't know what
to replace it with. From today's experience, i would feel confident
with : rep = getchar() ;

To make sure, the buffer doesn't grab new line '\n' from the rep
input, this could be a way to skip it : while ( getchar() != '\n' ) .

                                           break ; /* does break quit the if from if (strcmp(buffer,
"0")) ??? */
No.

                           }
                           exit(1) ;

This is not a portable value to return from main.
                   }
                   strcpy(list, buffer) ;
                   i++ ;
           }
   } while ( i < 10     &&      strcmp(buffer, "0") ) ;

   for ( m = i - 1 ;       m > 0        ;       m-- )
           for ( n = 0     ;       n < m        ;       n++ )
                   if ( strcmp(list[n], list[n+1]) > 0 )  /* The author wrote list
instead of list[n], could it had been : strcmp( *list, *(list+1) ) ???

While those are syntactically correct they represent different logic.
If he had written *(list+n) and*(list+n+1), it would mean the same as
what your wrote.  The expression list as an argument to strcmp without
some kind of dereference operator is a constraint violation.


I barely can see at my level what a dereference operation and a
constraint violation are.

I think i know dereference operation have to do with pointers but then
i'm not sure of what to do with this information.
*/
                   {
                           temp = list[n] ;
                           list[n] = list[n+1] ;
                           list[n+1] = temp ;
                   }
   if ( i > 0 )
   {
           printf("\nENTRY LISTING : \n") ;
           for ( m = 0     ;       m < i        ;       m++ )
                   printf("%s\n", list[m] ) ;
   }
   for ( m = 0     ;       m < i        ;       m++ )
           free(list[m]) ;

A return with either 0 or EXIT_SUCCESS would be nice here.

Would programs in 1995-96 include this ?
Are you sure you copied it correctly?

I made a few changes to meet today's standard however i'm not sure if
i made these changes correctly.



Thanks
 
A

Antoninus Twink

Ha! I nearly did use char for that one, and changed my mind at the
last moment because I guessed (wrongly, it seems) that I'd draw
flak for breaking consistency with other character handling
routines.
[snip]

Er, kindasorta, yes. Anyway, I always use int for Booleans.
[snip]

I see your point - I had forgotten that fgets takes an int, not a
size_t - and I half-agree with it. But only half.

So where is this famous Heathfield humility in accepting correction when
errors are pointed out to him?

All I see is a pathetic worm wriggling and squirming, trying to do
anything to get out of admitting he screwed up. He reminds me more of a
politician than a programmer.

Especially the last point - the risk of UB when passing a size_t or
ssize_t that's too big to fit in an int to an older-vintage function
like fgets() is a classic portability gotcha of the type Heathfield
loves to make a big thing of when other people do it. Hypocrite.
 

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

Members online

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top