473,794 Members | 2,708 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Comments on my code?

Hi-

I am learning C from some old lecture notes, but they don't have
solutions so I'd like some feedback on my code if anyone has the time.

This is an exercise: "Write a program to trim any leading whitespace
from a string and return a newly allocated buffer containing the trimmed
string. Don't forget to handle errors."

main(argc, argv)
int argc; char **argv;
{
char *strtrim(), *r=0;
puts(argc>1 && (r=strtrim(*++a rgv)) ? r : "Unspecifie d error");
free(r);
}

/* trims initial whitespace */
char *strtrim(s)
char *s;
{
char *r, *malloc();
for( ; isspace(*s); s++);
r=malloc(strlen (s)+1);
if(r)
strcpy(r,s);
return r;
}

This looks OK to me and works correctly, but the compiler produces some
mysterious warnings about conflicting definitions that I don't really
understand.
--
How come we never talk anymore?
Sep 1 '07 #1
28 1688
Platonic Solid wrote:
Hi-

I am learning C from some old lecture notes, but they don't have
solutions so I'd like some feedback on my code if anyone has the time.

This is an exercise: "Write a program to trim any leading whitespace
from a string and return a newly allocated buffer containing the trimmed
string. Don't forget to handle errors."

main(argc, argv)
int argc; char **argv;
{
char *strtrim(), *r=0;
puts(argc>1 && (r=strtrim(*++a rgv)) ? r : "Unspecifie d error");
free(r);
}

/* trims initial whitespace */
char *strtrim(s)
char *s;
{
char *r, *malloc();
for( ; isspace(*s); s++);
r=malloc(strlen (s)+1);
if(r)
strcpy(r,s);
return r;
}

This looks OK to me and works correctly, but the compiler produces some
mysterious warnings about conflicting definitions that I don't really
understand.
--
How come we never talk anymore?
You should not declare malloc like that.
#include <stdlib.h>
and never define your own definitions for library functions.

You need
#include <string.h>
for strlen's prototype.

And:
char *strtrim(s)
char *s;
This is old fashioned C. Better is:
char *strtrim(char *s)
P.S. What happens when s is NULL?

jacob
Sep 1 '07 #2
Platonic Solid wrote:
Hi-

I am learning C from some old lecture notes, but they don't have
solutions so I'd like some feedback on my code if anyone has the time.

This is an exercise: "Write a program to trim any leading whitespace
from a string and return a newly allocated buffer containing the trimmed
string. Don't forget to handle errors."

main(argc, argv)
int argc; char **argv;
{
char *strtrim(), *r=0;
puts(argc>1 && (r=strtrim(*++a rgv)) ? r : "Unspecifie d error");
free(r);
}

/* trims initial whitespace */
char *strtrim(s)
char *s;
{
char *r, *malloc();
for( ; isspace(*s); s++);
r=malloc(strlen (s)+1);
if(r)
strcpy(r,s);
return r;
}

This looks OK to me and works correctly, but the compiler produces some
mysterious warnings about conflicting definitions that I don't really
understand.
The program you wrote would be a correct way to write code a long time ago,
so if your lecture notes were really old, then well done. It's not a right
way to do things now, though. Try this version, and see if you understand
the changes I made:

#include <stdio.h /* include the headers that declare the library */
#include <stdlib.h/* functions and objects you are using. you should */
#include <string.h/* not declare them in your own program, especially*/
#include <ctype.h /* the wrong way; that is what caused your warning */

/*
* a forward declaration for your function should not be local to
* another function. also, you can specify the types of the parameters
* in the declaration as well as the definition. doing so allows the
* compiler to check and automatically convert the values you will be
* passing to the function.
*
* I renamed the function because technically, strtrim isn't a valid name
* for it, but the reasons why probably won't be of interest to you at
* this stage.
*/
char *trimstr(char *);

/*
* the types of the parameters should be specified in the parameter list,
* not between the ) and {. it's still valid, but has the same problems
* as not specifying the parameter types in the function declaration.
* and you should specify the return type, even if it's int.
*/
int main(int argc, char **argv) {
/*
* for readability reasons, I would recommend against your use of ?:,
* and use if statements instead.
*/
if (argc 1) {
char *r = trimstr(argv[1]);
if (!r) {
/* error messages should normally go to stderr, not stdout */
fputs("Unspecif ied error\n", stderr);
} else {
puts(r);
free(r);
}
}
/* main returns int (even in your original version), so return an int */
return 0;
}

char *trimstr(char *s) {
char *r;
/* for readability, you can rewrite your for loop */
while (isspace(*s))
s++;
/*
* malloc doesn't need to be declared manually here, with <stdlib.h>
* included. and malloc doesn't return 'char *' anymore, but 'void *'
* void is probably not covered in your lecture notes, but in the
* context of pointers, it means a pointer to any object, but you
* don't have the object's type.
*/
r = malloc(strlen(s )+1);
if(r)
strcpy(r,s);
return r;
}
Sep 1 '07 #3
On 1 Sep 2007 at 12:53, jacob navia wrote:
P.S. What happens when s is NULL?
If you look carefully I check argc>1, so it never gets called with s
null.

--
How come we never talk anymore?
Sep 1 '07 #4
On Sat, 01 Sep 2007 14:01:58 +0200, Platonic Solid wrote:
Hi-

I am learning C from some old lecture notes, but they don't have
solutions so I'd like some feedback on my code if anyone has the time.

This is an exercise: "Write a program to trim any leading whitespace
from a string and return a newly allocated buffer containing the trimmed
string. Don't forget to handle errors."

main(argc, argv)
int argc; char **argv;
In modern C this is usually written as
int main(int argc, char *argv[])
But the old form continues to work, even it "looks strange".
{
char *strtrim(), *r=0;
Better put function declaration at file scope, and use NULL
defined in <stddef.hand other headers instead of 0. Of course
your form will work, too, but it is "ugly".
puts(argc>1 && (r=strtrim(*++a rgv)) ? r : "Unspecifie d error");
To somebody which doesn't remember all the precedence rules by
heart, this could be confusing. If you *really* think that if/else
is evil (it isn't, at least it'd allow you to write the error
message to stderr), at least put parentheses around the first
operand of ?: ...
<nitpick pedantry="high" >Nowadays puts() takes a const char *,
but you're passing it a char *, because there is no prototype in
scope.</nitpickEven if it is overwhelmingly likely to work,
usually one use the prototype for puts() found in <stdio.h>.
free(r);
}

/* trims initial whitespace */
char *strtrim(s)
char *s;
{
char *r, *malloc();
In modern C malloc returns a void*, not a char*. Also the argument
is a size_t, see FAQ 7.15.
for( ; isspace(*s); s++);
r=malloc(strlen (s)+1);
strlen returns a size_t, but here you're declaring it as returning
an int.
if(r)
strcpy(r,s);
return r;
}

This looks OK to me and works correctly, but the compiler produces some
mysterious warnings about conflicting definitions that I don't really
understand.
See FAQ 11.29a for compatibility problem between old and new C.
--
Army1987 (Replace "NOSPAM" with "email")
No-one ever won a game by resigning. -- S. Tartakower

Sep 1 '07 #5
Platonic Solid wrote:
On 1 Sep 2007 at 12:53, jacob navia wrote:
>P.S. What happens when s is NULL?

If you look carefully I check argc>1, so it never gets called with s
null.

--
How come we never talk anymore?
Sure, but is strtrim only for this particular call?
In that case a function is not necessary!
Sep 1 '07 #6
On 2007-09-01 13:26, jacob navia <ja***@jacob.re mcomp.frwrote:
Platonic Solid wrote:
>On 1 Sep 2007 at 12:53, jacob navia wrote:
>>P.S. What happens when s is NULL?

If you look carefully I check argc>1, so it never gets called with s
null.

Sure, but is strtrim only for this particular call?
In that case a function is not necessary!
What happens when you call strlen(NULL)?

hp
--
_ | Peter J. Holzer | I know I'd be respectful of a pirate
|_|_) | Sysadmin WSR | with an emu on his shoulder.
| | | hj*@hjp.at |
__/ | http://www.hjp.at/ | -- Sam in "Freefall"
Sep 1 '07 #7
On 2007-09-01 12:59, Harald van Dijk <tr*****@gmail. comwrote:
Platonic Solid wrote:
>I am learning C from some old lecture notes, but they don't have
solutions so I'd like some feedback on my code if anyone has the time.
[ lots of good advice snipped]

char *trimstr(char *s) {
char *r;
/* for readability, you can rewrite your for loop */
while (isspace(*s))
s++;
isspace expects an argument in the range [EOF, 0 .. UCHAR_MAX]. But
*s will be in the range [CHAR_MIN .. CHAR_MAX], so isspace may be called
with an illegal value, resulting in undefined behaviour.

You must get the value into the correct range first:

while (isspace((unsig ned char)*s))
s++;

hp

--
_ | Peter J. Holzer | I know I'd be respectful of a pirate
|_|_) | Sysadmin WSR | with an emu on his shoulder.
| | | hj*@hjp.at |
__/ | http://www.hjp.at/ | -- Sam in "Freefall"
Sep 1 '07 #8
Platonic Solid wrote:
Hi-

I am learning C from some old lecture notes, but they don't have
solutions so I'd like some feedback on my code if anyone has the time.
Judging from your code, these are extremely old lecture notes. If there
is a date on them, I would guess it to be somewhere in the 1980's.
Since that time, C has evolved a bit. Not too much but enough that it
would be worthwhile to have a more recent book to accompany these
lecture notes.
I would suggest you get a copy of "The C Programming Language", second
edition, by Kernighan and Ritchie (often referred to as K&R2)
>
This is an exercise: "Write a program to trim any leading whitespace
from a string and return a newly allocated buffer containing the
trimmed string. Don't forget to handle errors."
To use library functions, you should #include the appropriate headers.
For this program, you need

#include <stdio.h/* for puts() */
#include <stdlib.h/* for malloc()/free() */
#include <ctype.h/* for isspace() */
#include <string.h/* for strcpy() */
main(argc, argv)
int argc; char **argv;
This style of declaring parameters is considered to be outdated.
It is preferred that you write it now like this:
int main(int argc, char **argv)
{
char *strtrim(), *r=0;
It is not wrong to declare a function at this point, but it is not
considered to be good style.
It is recommended that you declare functions at file scope, and that you
give a prototype for the function.
The prototype for strtrim() looks like
char *strtrim(char*) ;
The advantage of a prototype is that the compiler can verify (and
complain!) that you call the function in the correct way.

As a more personal style issue, I prefer to have one item per
declaration. I would have written the above declaration as:
char *strtrim(char*) ;
char *r;
I also might have used a more descriptive name for r.
puts(argc>1 && (r=strtrim(*++a rgv)) ? r : "Unspecifie d error");
C allows you to write extremely complex expressions, but usually it is
best to avoid using that freedom. (exception: IOCCC entries)
The statement above is right at the limit of how complex you should make
it (and some would argue it is over the limit).
free(r);
As main() returns a success/failure code to the OS, you should make sure
that it is a sensible code:
return 0; /* indicates success. Other code are EXIT_SUCCESS and
EXIT_FAILURE */
}

/* trims initial whitespace */
char *strtrim(s)
char *s;
Same comment as with main(): you should place the argument type also
within the parentheses.
char *strtrim(char *s)
{
char *r, *malloc();
You should not write a declaration for library functions, like malloc().
Instead you should #include the required header (see above).
for( ; isspace(*s); s++);
r=malloc(strlen (s)+1);
if(r)
strcpy(r,s);
return r;
}

This looks OK to me and works correctly, but the compiler produces
some mysterious warnings about conflicting definitions that I don't
really understand.
Those warnings are probably due to the required headers that you forgot
to include.
Modern compilers will complain if the encounter a call to a function
that they have not yet seen before (like your calls to puts, isspace
and strcpy). The complaints are because the compiler has to make some
assumptions that are likely to be wrong.

BTW, if you have questions about compiler messages, it works so much
better if you post the compiler output (along with the code you fed
into the compiler). Most of us will know immediately what it means,
because we have seen the message before.

Bart v Ingen Schenau
--
a.c.l.l.c-c++ FAQ: http://www.comeaucomputing.com/learn/faq
c.l.c FAQ: http://www.eskimo.com/~scs/C-faq/top.html
c.l.c++ FAQ: http://www.parashift.com/c++-faq-lite/
Sep 1 '07 #9
Peter J. Holzer wrote:
On 2007-09-01 12:59, Harald van Dijk <tr*****@gmail. comwrote:
>Platonic Solid wrote:
>>I am learning C from some old lecture notes, but they don't have
solutions so I'd like some feedback on my code if anyone has the time.

[ lots of good advice snipped]

>char *trimstr(char *s) {
char *r;
/* for readability, you can rewrite your for loop */
while (isspace(*s))
s++;

isspace expects an argument in the range [EOF, 0 .. UCHAR_MAX]. But
*s will be in the range [CHAR_MIN .. CHAR_MAX], so isspace may be called
with an illegal value, resulting in undefined behaviour.

You must get the value into the correct range first:

while (isspace((unsig ned char)*s))
s++;
Thanks, I forgot about that. It would be nice if I could get my system to
warn about passing a char; it's not the first time I've left out the cast.
Sep 1 '07 #10

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

Similar topics

4
3379
by: Sims | last post by:
Hi, I proud myself in having good comments, (/**/, // etc...), all over my scripts as well as a very descriptive section at the beginning of the script. No correct me if i am wrong but php must still 'read' those comments? So, do comments technically slow the whole process? Or is the loss of CPU/Time/memory so negligible that i do not need to worry about it.
17
2755
by: lkrubner | last post by:
I've got a PHP application that's 2 megs in size. Of that, my guess is 200k-400k is comments. Do they impose a performance hit? I've been postponing any kind of optimization, but at some point I'll have to do it. Is taking out the comments worth it? Of all the optimizations I can do, where should it rank?
28
3465
by: Benjamin Niemann | last post by:
Hello, I've been just investigating IE conditional comments - hiding things from non-IE/Win browsers is easy, but I wanted to know, if it's possible to hide code from IE/Win browsers. I found <!> in the original MSDN documentation, but this is (although it is working) unfortunately non-validating gibberish. So I fooled around trying to find a way to make it valid. And voila: <!--><!><!-->
10
2093
by: Monk | last post by:
Hi, Have a query regarding comments that extend over multiple-lines. Would like to know if the standard's view of this, so that we can create a code which doesn't run into compiler specific issues. 1. A normal comments is /* comment text */ 2. A multiple line comment is
40
4645
by: Edward Elliott | last post by:
At the risk of flogging a dead horse, I'm wondering why Python doesn't have any multiline comments. One can abuse triple-quotes for that purpose, but that's obviously not what it's for and doesn't nest properly. ML has a very elegant system for nested comments with (* and *). Using an editor to throw #s in front of every line has limitations. Your editor has to support it and you have to know how to use that feature. Not exactly...
98
4627
by: tjb | last post by:
I often see code like this: /// <summary> /// Removes a node. /// </summary> /// <param name="node">The node to remove.</param> public void RemoveNode(Node node) { <...> }
2
7341
by: beatTheDevil | last post by:
Hey guys, As the title says I'm trying to make a regular expression (regex/regexp) for use in removing the comments from code. In this case, this particular regex is meant to match /* ... */ comments. I'm using Ruby v.1.8.6 Here's my regex: multiline_comments = /\/\*(.*?)\*\// When I try myStr.gsub(multiline_comments, "")
2
5388
by: mad.scientist.jr | last post by:
In .NET 2.0, is there any way to include comments in the aspx file that do not get rendered to the client (ie no <!-- -->) ? When I try to include C# comments in a code block in an aspx page, like this: <% // ******************************************************* // CHANGE HISTORY: // DATE USER CHANGE
6
12000
by: Marjeta | last post by:
I was trying to compare a particular trigger on multiple servers. First I tried phpMyAdmin to script the trigger code, which unfortunately only worked on one server that has newer version of phpMyAdmin... Then I used mysqldump, which scripted trigger code on all the servers, bur with comments around all the trigger related code: phpMyAdmine scripted trigger code without comments. Why are those comments there? I searched thru...
0
9671
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9518
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
10433
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
1
10161
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
10000
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
5436
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...
0
5560
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
2
3720
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2919
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.