473,797 Members | 3,148 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Going through the code (K&R 1-19.c)

First of all let me apologize for being so "green".
You must have been pretty fed up with newbish questions, but,
still I felt, that's the only place I could get a decent answer.

Haven't been able to solve the 1-19 exercise (page 31) from K&R book,
I decided, it's time to cheat, so I took peek at:
http://users.powernet.co.uk/eton/kandr2/krx119.html

Still I would not understand certain things, I will place the
code, with my comments as me trying to figure it out. Grep for "why".

#include <stdio.h>
#define MAX_LINE 1000

void discard_nl(char s[]);
int reverse(char s[]);
int getline(char s[], int lim);

/* inserts a "end-of-string" instead of \n; why do we need \0? */
void discard_nl(char s[])
{
int i;
for (i = 0; s[i] != '\0'; i++)
{
if (s[i] == '\n')
s[i] = '\0';
/* replaces \n with \0 */
}
}

/* the reverse function itself */
int reverse(char s[])
{
char ch;
int i, j;

for(j = 0; s[j] != '\0'; j++) /* going through array \ */
{ /* indexes */
;
}
--j; /* what is it? why is the array one element less? */

for(i =0; i < j; i++)
{
ch = s[i]; /* storing each value in ch */
s[i] = s[j]; /* first value equals last value */
s[j] = ch; /* las value equals first (ch) value */
--j; /* shrinking the number of i < j to be
* checked */
}
return 0;
}
/* getline: all chars up to \n; \n and \0 inserted afterwords, why? */
int getline(char s[], int lim)
{
int c, i;

for(i = 0; i < lim -1 && (c = getchar()) != EOF && c != '\n'; ++i)
s[i] = c;
if (c == '\n')
s[i++] = c; /* or: s[i] = '\n'; ++i; */
s[i] = '\0'; /* inserting "end-of-string" \0 */
return i;
}

int main()
{

char line[MAX_LINE];
while(getline(l ine, MAX_LINE) > 0) /* changed it to MAX_LINE \ */
{ /* instead of "sizeof line" \ */
discard_nl(line ); /* by me */
reverse(line);
printf("%s\n", line);
}
return 0;
}

Any added comments are welcome. I won't be disappointed if someone skips
the post. Thank you. -nabis

Nov 14 '05 #1
6 1332
nabis wrote on 31/07/04 :
Still I would not understand certain things, I will place the
code, with my comments as me trying to figure it out. Grep for "why".

#include <stdio.h>
#define MAX_LINE 1000

void discard_nl(char s[]);
int reverse(char s[]);
int getline(char s[], int lim);

/* inserts a "end-of-string" instead of \n; why do we need \0? */
'\0' is the character-oriented-way version of 0. You can use 0 if you
feel more comfortable.

(Note, but I'm quite sure you are aware of that: 0 is the end-of-string
marker)
void discard_nl(char s[])
{
int i;
for (i = 0; s[i] != '\0'; i++)
{
if (s[i] == '\n')
s[i] = '\0';
/* replaces \n with \0 */
}
}

/* the reverse function itself */
int reverse(char s[])
{
char ch;
int i, j;

for(j = 0; s[j] != '\0'; j++) /* going through array \ */
{ /* indexes */
;
}
--j; /* what is it? why is the array one element less? */
The best is to draw the string and index on a paper and see what
happens step by step at each turn of the loop. This kind of job is part
of the debugging process a programmer is supposed to masterize.

for(i =0; i < j; i++)
{
ch = s[i]; /* storing each value in ch */
s[i] = s[j]; /* first value equals last value */
s[j] = ch; /* las value equals first (ch) value */
--j; /* shrinking the number of i < j to be
* checked */
}
return 0;
} /* getline: all chars up to \n; \n and \0 inserted afterwords, why? */
Because of the purpose of the function: 'Get a line'. The end-of-line
marker belongs to the line (in normal conditions), and a decent
C-string must be terminated by a 0 (always).

Note that is there is no room enough, the '\n' is not present, hence
this status (trimmed line) can be detected by the user. This behaviour
is similar to the one of fgets().
int getline(char s[], int lim)
{
int c, i;

for(i = 0; i < lim -1 && (c = getchar()) != EOF && c != '\n'; ++i)
s[i] = c;
if (c == '\n')
s[i++] = c; /* or: s[i] = '\n'; ++i; */
s[i] = '\0'; /* inserting "end-of-string" \0 */
return i;
}

int main()
{

char line[MAX_LINE];
while(getline(l ine, MAX_LINE) > 0) /* changed it to MAX_LINE \ */
{ /* instead of "sizeof line" \ */
discard_nl(line ); /* by me */
Why ? It's not wrong, but unnecessary. 'sizeof line' was the good way
(as far as 'line' is an array of char).
reverse(line);
printf("%s\n", line);
}
return 0;
}


--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html

"C is a sharp tool"

Nov 14 '05 #2
Shug Boabie <no*****@exampl e.com> writes:
nabis wrote:
for(j = 0; s[j] != '\0'; j++)

here we (in order) increment j and then check the j'th element of
s[] to see if it is NULL.


NULL is a macro that expands to a null pointer constant; it's not a
null character.

The best way to refer to a null character is '\0'.

--
Keith Thompson (The_Other_Keit h) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 14 '05 #3
(supersedes <mn************ ***********@YOU RBRAnoos.fr>)

nabis wrote on 31/07/04 :
Still I would not understand certain things, I will place the
code, with my comments as me trying to figure it out. Grep for "why".

#include <stdio.h>
#define MAX_LINE 1000

void discard_nl(char s[]);
int reverse(char s[]);
int getline(char s[], int lim);

/* inserts a "end-of-string" instead of \n; why do we need \0? */
'\0' is the character-oriented-way version of 0. You can use 0 if you
feel more comfortable.

(Note, but I'm quite sure you are aware of that: 0 is the end-of-string
marker)
void discard_nl(char s[])
{
int i;
for (i = 0; s[i] != '\0'; i++)
{
if (s[i] == '\n')
s[i] = '\0';
/* replaces \n with \0 */
}
}

/* the reverse function itself */
int reverse(char s[])
{
char ch;
int i, j;

for(j = 0; s[j] != '\0'; j++) /* going through array \ */
{ /* indexes */
;
}
--j; /* what is it? why is the array one element less? */
The best is to draw the string and index on a paper and see what
happens step by step at each turn of the loop. This kind of job is part
of the debugging process a programmer is supposed to masterize.
for(i =0; i < j; i++)
{
ch = s[i]; /* storing each value in ch */
s[i] = s[j]; /* first value equals last value */
s[j] = ch; /* las value equals first (ch) value */
--j; /* shrinking the number of i < j to be
* checked */
}
return 0;
} /* getline: all chars up to \n; \n and \0 inserted afterwords, why? */
Because of the purpose of the function: 'Get a line'. The end-of-line
marker belongs to the line (in normal conditions), and a decent
C-string must be terminated by a 0 (always).

Note that if there is no room enough, the '\n' is not present, hence
this status (trimmed line) can be detected by the user. This behaviour
is similar to the one of fgets().
int getline(char s[], int lim)
{
int c, i;

for(i = 0; i < lim -1 && (c = getchar()) != EOF && c != '\n'; ++i)
s[i] = c;
if (c == '\n')
s[i++] = c; /* or: s[i] = '\n'; ++i; */
s[i] = '\0'; /* inserting "end-of-string" \0 */
return i;
}

int main()
{

char line[MAX_LINE];
while(getline(l ine, MAX_LINE) > 0) /* changed it to MAX_LINE \
*/
{ /* instead of "sizeof line" \
*/
discard_nl(line ); /* by me
*/
Why ? It's not wrong, but unnecessary. 'sizeof line' was the good way
(as far as 'line' is an array of char).
reverse(line);
printf("%s\n", line);
}
return 0;
}


--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html

"C is a sharp tool"

Nov 14 '05 #4
Thank you for your answers.
I tried to see what happens to a string "hello" as it passes through the
functions in order they appear in main(). It clarified some things.
My question is, was it necessary to insert a '\n' in getline() and to remove
this same '\n' in discard_nl(), also do we need to carry '\0' through all
the functions, can't we inset it in the last reverse() function?

-nabis
-----------------------------------------------------------------------------
(Just my notes)
1)getline:

s[0] = 'h'; s[1] = 'e'; s[2] = 'l'; s[3] = 'l'; s[4] = 'o' (exits the loop at
s[5] == '\n')
s[5] = '\n' ; s[6] = '\0' (newline and end-of-string inserted)

the for loop, even after "i < lim -1 && (c = getchar()) != EOF && c != '\n'"
has been tested, and proven false, the ++i increment had taken place, so
we can assign '\n' to s[5]?) Probably, yes:
for (i = 0; i < 10; ++i)
printf("%d ", i);
printf("\n%d\n" , i);
output:
0 1 2 3 4 5 6 7 8 9
10
2)discard_nl:

results in
s[0] = 'h'; s[1] = 'e'; s[2] = 'l'; s[3] = 'l'; s[4] = 'o';
s[5] = '\0'; s[6] = '\0';
(there are *two* '\0' in s[] now, am I wrong?)
3)reverse:

j = 4 (after the first for loop and --j, which is right, we want to
manipulate s[0] through s[4])
second for loop:
i = 0 ; ch = s[0] = 'h';
s[0] = s[4] = 'o';
s[4] = 'h';
j = 3;
i = 1; ch = s[1] = 'e';
s[1] = s[3] = 'l';
s[3] = 'e';
j = 2;
i = 2; ch = s[2] = 'l';
s[2] = s[2] = 'l';
s[2] = 'l';
j = 3;
i < j is false, exiting the loop.

our s[] = "olleh\0\0" at this moment?
01234 5 6 (indexes)

Nov 14 '05 #5
On Sun, 01 Aug 2004 05:53:49 -0500, nabis <na***@tiny.net > wrote:
Thank you for your answers.
I tried to see what happens to a string "hello" as it passes through the
functions in order they appear in main(). It clarified some things.
My question is, was it necessary to insert a '\n' in getline() and to remove
Probably not but the '\n' is considered part of the line so this
preserves some measure of consistency.
this same '\n' in discard_nl(), also do we need to carry '\0' through all
the functions, can't we inset it in the last reverse() function?
How would you know where to insert it?

-nabis
-----------------------------------------------------------------------------
(Just my notes)
1)getline:

s[0] = 'h'; s[1] = 'e'; s[2] = 'l'; s[3] = 'l'; s[4] = 'o' (exits the loop at
s[5] == '\n')
s[5] = '\n' ; s[6] = '\0' (newline and end-of-string inserted)

the for loop, even after "i < lim -1 && (c = getchar()) != EOF && c != '\n'"
has been tested, and proven false, the ++i increment had taken place, so
we can assign '\n' to s[5]?) Probably, yes:
for (i = 0; i < 10; ++i)
printf("%d ", i);
printf("\n%d\n" , i);
output:
0 1 2 3 4 5 6 7 8 9
10
2)discard_nl :

results in
s[0] = 'h'; s[1] = 'e'; s[2] = 'l'; s[3] = 'l'; s[4] = 'o';
s[5] = '\0'; s[6] = '\0';
(there are *two* '\0' in s[] now, am I wrong?)
No. But the string is terminated by the first one. While the second
'\0' is in the array, it is not part of the string.


3)reverse:

j = 4 (after the first for loop and --j, which is right, we want to
manipulate s[0] through s[4])
second for loop:
i = 0 ; ch = s[0] = 'h';
s[0] = s[4] = 'o';
s[4] = 'h';
j = 3;
i = 1; ch = s[1] = 'e';
s[1] = s[3] = 'l';
s[3] = 'e';
j = 2;
i = 2; ch = s[2] = 'l';
s[2] = s[2] = 'l';
s[2] = 'l';
j = 3;
i < j is false, exiting the loop.

our s[] = "olleh\0\0" at this moment?
01234 5 6 (indexes)


Yup
<<Remove the del for email>>
Nov 14 '05 #6
In article <10************ *@corp.supernew s.com> nabis <na***@tiny.net > wrote:
My question is, was it necessary to insert a '\n' in getline() and to remove
this same '\n' in discard_nl() ...
Clearly not; but if you already have working code that does "a
little bit too much" you can re-use it by "un-doing" the extra
work.

The getline() function in K&R is preparing you for using the
Standard C fgets() function, which also keeps the '\n' that you
will often wind up discarding afterward.
also do we need to carry '\0' through all
the functions, can't we inset it in the last reverse() function?
Again, "clearly not" -- but the '\0' in a C string has a reason
for its existence, which also relates to:
s[0] = 'h'; s[1] = 'e'; s[2] = 'l'; s[3] = 'l'; s[4] = 'o';
s[5] = '\0'; s[6] = '\0';
(there are *two* '\0' in s[] now, am I wrong?)


You are correct.

C's strings are not really a *type* but rather a *data structure*:
any sequence of characters that ends with '\0' can be considered a
"string". Functions that deal with "C strings" simply look for the
first (and perhaps only, or perhaps one of many) '\0' bytes -- once
they see it they stop. A function that is documented to take "a
string" may (depending on whoever wrote it) keep going and going,
way past the end of an array of "char", looking for the '\0' that
tells it to stop, if you pass it an array that does not contain a
terminating '\0'.

Extra bytes in any array past the first '\0' get ignored, so you
can shorten a string that is stored in some "array N of char" array
by writing a '\0' before its current '\0' end-marker. This is
often convenient (as is the case in discard_nl()).

Hence, if you wanted not to carry the '\0' through all the various
functions, you would have to stop using C strings -- which only
stop when they hit that '\0'. Any code that depends on that '\0'
(such as a call to strlen(), or an inline expansion of strlen that
"manually" looks for '\0') would have to change.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Nov 14 '05 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
1823
by: Aldo | last post by:
hello i'm trying to translate this asp code to php, but i can't get it work right. could anyone help me? thanks! a. ASP CODE ---------------------
14
2509
by: Stuart D. Gathman | last post by:
I have a function that recognizes PTR records for dynamic IPs. There is no hard and fast rule for this - every ISP does it differently, and may change their policy at any time, and use different conventions in different places. Nevertheless, it is useful to apply stricter authentication standards to incoming email when the PTR for the IP indicates a dynamic IP (namely, the PTR record is ignored since it doesn't mean anything except to...
7
1350
by: Randy Yates | last post by:
OK, why doesn't this work: string EraseCommas(string &numericString) { UINT16_T commaPosition; commaPosition = numericString.find(","); while (commaPosition != string::npos); {
4
1855
by: sea | last post by:
I have a database in Access 2002 but I am unable to view code or write any modules when logged in with a limited user account using Windows XP, service pack 2 -- no problems when logging in as administrator, -- any ideas on how a limited user on Windows XP can access code and modules in Access 2002? Thank you very much.
3
1998
by: Lyle Fairfield | last post by:
Sometimes we use script or code whose variable types do not correspond to the variable types of other technologies with which they interface. It's possible that our db provider may come to our rescue, both by applyling its functions and by "returning" a compatible dtat type. Here is a VBA-ADO-MS-SQL example. It uses MS-SQL functions to trim a string. (Yes, I know VBA has these functions; I am attempting to demonstrate a capability, not...
3
2740
by: Niklas Uhlin | last post by:
Why does the code below output this: "v a" (118,32,97) "w a" (119,32,97) "v b" (118,32,98) "w b" (119,32,98) "v c" (118,32,99) "w c" (119,32,99) and not this (as one would expect if Array.Sort sorted by character code value):
1
4501
by: Garry Jones | last post by:
I have been using this code for sometime. I can use it to show the user how many remaining characters are reamaining in a text area. Now I need to develop the code and dont know where to start. These are the three parts of the working code 1) Javascript function taLimit() { var taObj=event.srcElement;
18
1635
tpgames
by: tpgames | last post by:
How do I get code to access the images at the URL given? I'd like the user to be able to select which theme of images they want to view then the script would randomly pick an image to show. <!--BEGIN // Customising Variables // Arrays of Images that can be used in the game var ImgAry=; var ImgAry2=; var ImgAry3=;
0
9536
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10021
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
9063
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
7559
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6802
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5458
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
1
4131
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
3748
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2933
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.