Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #72816 > unrolled thread
| Started by | Alla _ <modelling.data@gmail.com> |
|---|---|
| First post | 2015-10-14 03:24 -0700 |
| Last post | 2015-10-14 21:22 +0100 |
| Articles | 10 — 5 participants |
Back to article view | Back to comp.lang.c
Program to extract a substring from a string; compiling issues Alla _ <modelling.data@gmail.com> - 2015-10-14 03:24 -0700
Re: Program to extract a substring from a string; compiling issues Bartc <bc@freeuk.com> - 2015-10-14 11:49 +0100
Re: Program to extract a substring from a string; compiling issues Alla _ <modelling.data@gmail.com> - 2015-10-14 05:17 -0700
Re: Program to extract a substring from a string; compiling issues Bartc <bc@freeuk.com> - 2015-10-14 13:31 +0100
Re: Program to extract a substring from a string; compiling issues Jorgen Grahn <grahn+nntp@snipabacken.se> - 2015-10-14 13:40 +0000
Re: Program to extract a substring from a string; compiling issues Alla _ <modelling.data@gmail.com> - 2015-10-14 07:46 -0700
Re: Program to extract a substring from a string; compiling issues Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-10-14 13:42 +0100
Re: Program to extract a substring from a string; compiling issues Alla _ <modelling.data@gmail.com> - 2015-10-14 08:14 -0700
Re: Program to extract a substring from a string; compiling issues Keith Thompson <kst-u@mib.org> - 2015-10-14 11:23 -0700
Re: Program to extract a substring from a string; compiling issues Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-10-14 21:22 +0100
| From | Alla _ <modelling.data@gmail.com> |
|---|---|
| Date | 2015-10-14 03:24 -0700 |
| Subject | Program to extract a substring from a string; compiling issues |
| Message-ID | <ddd5630d-29e4-4664-9f19-06aaf72dce6c@googlegroups.com> |
Hello!
Here is a small program I have written (textbook task)
that should extract a substring from a word.
Unfortunately, the compiler doesn't except my effort :)
Please, take a look at the program, and at another option
of the last two lines from the main function - doesn't work
either.
// Program to extract a substring from a string
#include <stdio.h>
int string_length (const char string[]);
void substring (char source[], int start, int count);
int main (void)
{
char word [] = "alphabetical";
char subword[81];
int start_letter = 3, count_number = 4;
printf("Note that the length of the word is %i\n", string_length (word));
subword [] = substring (word, start_letter, count_number);
printf("Your word is %s", subword);
return 0;
}
int string_length (const char string[])
{
int count = 0;
while (string[count] != '\0')
count++;
return count;
}
void substring (char source[], int start, int count)
{
int i;
char result [80];
if (count > string_length (source))
{
for (i = start; i <= (start + count) && source[i] != '\0'; i++)
{
result [i] = source [i];
}
result [i + 1] = '\0';
}
else
{
for (i = start; i <= (start + count); i++)
{
result [i] = source [i];
}
result [i + 1] = '\0';
}
}
I assume that the following part somehow causes problems:
subword [] = substring (word, start_letter, count_number);
printf("Your word is %s", subword);
Error: ex9-4A.c: In function 'main':
ex9-4A.c:16: error: expected expression before ']' token
Here is another option I have tested:
1) printf("Note that the length of the word is %i\n", string_length (word));
printf("Your word is %s", substring (word, start_letter, count_number));
return 0;
// Skipped the subword part
Error: ex9-4A.c: In function 'main':
ex9-4A.c:16: error: invalid use of void expression
Thank you!
[toc] | [next] | [standalone]
| From | Bartc <bc@freeuk.com> |
|---|---|
| Date | 2015-10-14 11:49 +0100 |
| Message-ID | <mvlbs2$jv1$1@dont-email.me> |
| In reply to | #72816 |
On 14/10/2015 11:24, Alla _ wrote: > char subword[81]; > subword [] = substring (word, start_letter, count_number); > void substring (char source[], int start, int count) These are the main problems: First, you haven't given an index to subword[]. It needs a subscript inside the []. Also, the function substring() doesn't return any value, which is also the root of the printf problem. And if substring did return a value, probably it would be a string (type char*), but you are assigning it to a single character inside subword. Suggested changes (bearing in mind I've just peeked at your code and don't know how it works): Change 'char subword[81];' to 'char* subword;'. Then it can point to a zero-terminated substring: subword = substring(...). Change subword() so that the return type is not void, but char*. And change it so that it returns 'result'. However, as it's defined now, result will disappear as soon as you return from the function. You can get around that temporarily by declaring it as 'static char result[80];', but that is not a good solution. Hard-coding limits such as 80 characters is not good either (it might have worked in the 1970s, but not know). So this requires a rethink of how substring returns a value. Perhaps the caller can supply a pointer to a destination, together with its size. But then you can't use substring() as you do in the printf call. I suggest you also document the functions to describe what they do, and what they return. Then that can help discover the problems. -- Bartc
[toc] | [prev] | [next] | [standalone]
| From | Alla _ <modelling.data@gmail.com> |
|---|---|
| Date | 2015-10-14 05:17 -0700 |
| Message-ID | <932b6060-b3e5-4883-9ca3-5bc0acebf2ad@googlegroups.com> |
| In reply to | #72819 |
On Wednesday, October 14, 2015 at 2:49:47 PM UTC+4, Bart wrote:
> On 14/10/2015 11:24, Alla _ wrote:
>
> > char subword[81];
>
> > subword [] = substring (word, start_letter, count_number);
>
> > void substring (char source[], int start, int count)
>
>
> These are the main problems:
>
> First, you haven't given an index to subword[]. It needs a subscript
> inside the [].
>
> Also, the function substring() doesn't return any value, which is also
> the root of the printf problem.
>
> And if substring did return a value, probably it would be a string (type
> char*), but you are assigning it to a single character inside subword.
>
> Suggested changes (bearing in mind I've just peeked at your code and
> don't know how it works):
>
> Change 'char subword[81];' to 'char* subword;'. Then it can point to a
> zero-terminated substring: subword = substring(...).
>
> Change subword() so that the return type is not void, but char*. And
> change it so that it returns 'result'. However, as it's defined now,
> result will disappear as soon as you return from the function.
>
> You can get around that temporarily by declaring it as 'static char
> result[80];', but that is not a good solution. Hard-coding limits such
> as 80 characters is not good either (it might have worked in the 1970s,
> but not know).
>
> So this requires a rethink of how substring returns a value. Perhaps the
> caller can supply a pointer to a destination, together with its size.
> But then you can't use substring() as you do in the printf call.
>
> I suggest you also document the functions to describe what they do, and
> what they return. Then that can help discover the problems.
>
> --
> Bartc
Thank you very much! Sorry for not adding
descriptions to my functions; I understand that
it's necessary. Will re-post the program now.
As to pointers, this topic will be covered in
the next chapter :) Thus doing this exercise
I guess I am supposed to find ways that do
require to use pointers (yet! until next chapter :) )
// Program to extract a substring from a string
#include <stdio.h>
int string_length (const char string[]);
void substring (char source[], int start, int count);
int main (void)
{
char word [] = "alphabetical";
char subword[81];
int start_letter = 3, count_number = 4;
printf("Note that the length of the word is %i\n", string_length (word));
printf("Your word is %s", substring (word, start_letter, count_number));
return 0;
}
/** Function to compute the length of a given word **/
int string_length (const char string[])
{
int count = 0;
while (string[count] != '\0')
count++;
return count;
}
/** Function to extract a substring from a given word, where
source = word, start = the first letter of a substring
within the word, count = number of letters in the sub-
string **/
void substring (char source[], int start, int count)
{
int i;
char result [80];
if (count > string_length (source))
{
for (i = start; i <= (start + count) && source[i] != '\0'; i++)
{
result [i] = source [i];
}
result [i + 1] = '\0';
}
else
{
for (i = start; i <= (start + count); i++)
{
result [i] = source [i];
}
result [i + 1] = '\0';
}
}
[toc] | [prev] | [next] | [standalone]
| From | Bartc <bc@freeuk.com> |
|---|---|
| Date | 2015-10-14 13:31 +0100 |
| Message-ID | <mvlhqm$9cc$1@dont-email.me> |
| In reply to | #72828 |
On 14/10/2015 13:17, Alla _ wrote: > On Wednesday, October 14, 2015 at 2:49:47 PM UTC+4, Bart wrote: >> I suggest you also document the functions to describe what they do, and >> what they return. Then that can help discover the problems. > Thank you very much! Sorry for not adding > descriptions to my functions; I understand that > it's necessary. Will re-post the program now. The description is supposed to help you rather than us! > /** Function to extract a substring from a given word, where > source = word, start = the first letter of a substring > within the word, count = number of letters in the sub- > string **/ > And this doesn't explain what is returned and how. It might return a pointer to an internal static string. Or into a buffer supplied by the caller. Or it will create a string in allocated memory and return a pointer to that. All these cases involve creating a copy of the substring, and it's where to put the space for that copy, which is the problem. If there are no limits in place, the substring can be of any size. There could also be an error (the substring is beyond the string bounds for example), and there might need to be a way of indicating that to the caller. And the caller would need to check that. But that probably too advanced for the purposes of your exercise. (And also: how much do you really want to program in C? In case you are not aware, there are far easier languages around!) > As to pointers, this topic will be covered in > the next chapter :) Thus doing this exercise > I guess I am supposed to find ways that do > require to use pointers (yet! until next chapter :) ) In C, dealing with strings is going to be difficult without pointers. Or perhaps the book thinks of string pointers as different. -- Bartc
[toc] | [prev] | [next] | [standalone]
| From | Jorgen Grahn <grahn+nntp@snipabacken.se> |
|---|---|
| Date | 2015-10-14 13:40 +0000 |
| Message-ID | <slrnn1smpu.5q5.grahn+nntp@frailea.sa.invalid> |
| In reply to | #72829 |
On Wed, 2015-10-14, Bartc wrote: > On 14/10/2015 13:17, Alla _ wrote: ... >> As to pointers, this topic will be covered in >> the next chapter :) Thus doing this exercise >> I guess I am supposed to find ways that do >> require to use pointers (yet! until next chapter :) ) > > In C, dealing with strings is going to be difficult without pointers. Yeah -- and sure enough, he has a pointer 'string' already: int string_length (const char string[]); int string_length (const char* string); // same thing > Or perhaps the book thinks of string pointers as different. That would be weird, but not unheard of ;-) Writing a textbook and introducing concepts in the right order must be difficult. /Jorgen -- // Jorgen Grahn <grahn@ Oo o. . . \X/ snipabacken.se> O o .
[toc] | [prev] | [next] | [standalone]
| From | Alla _ <modelling.data@gmail.com> |
|---|---|
| Date | 2015-10-14 07:46 -0700 |
| Message-ID | <d80fe261-1963-4267-bebd-ca7acbd8c58f@googlegroups.com> |
| In reply to | #72829 |
<snip> > (And also: how much do you really want to program in C? In case you are > not aware, there are far easier languages around!) > yes, I am aware of that; they say Python is much easier, as well as some other ones. But no, I am with C, at least for now :)
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2015-10-14 13:42 +0100 |
| Message-ID | <87y4f5aafc.fsf@bsb.me.uk> |
| In reply to | #72816 |
Alla _ <modelling.data@gmail.com> writes:
> Here is a small program I have written (textbook task)
> that should extract a substring from a word.
> Unfortunately, the compiler doesn't except my effort :)
>
> Please, take a look at the program, and at another option
> of the last two lines from the main function - doesn't work
> either.
>
> // Program to extract a substring from a string
>
> #include <stdio.h>
>
> int string_length (const char string[]);
> void substring (char source[], int start, int count);
substring returns no value (that's what the "void" means) so unless it
changes the string in source or does something like input or output it
can't have have useful function. And if you'd written
void substring (const char source[], int start, int count);
(as you should have) I'd know for sure that it's a pointless function!
> int main (void)
> {
> char word [] = "alphabetical";
> char subword[81];
> int start_letter = 3, count_number = 4;
>
> printf("Note that the length of the word is %i\n", string_length (word));
>
> subword [] = substring (word, start_letter, count_number);
You can't assign to an array in C, if that is what you are trying to do
(that would look more like subword = substring(...) so maybe that's not
what you are trying).
Pretty much the only viable option here is to pass into substring a
pointer to the (start of) the array into which the substring should be
copied.
<snip>
> void substring (char source[], int start, int count)
> {
> int i;
> char result [80];
Why 80? You can't know know that 80 is enough, but if you've picked a
size for an array, make sure you check that it is enough. Either refuse
to do anything if count >= 80, or only put a maximum of 79 characters
and a null into it.
> if (count > string_length (source))
This is not a useful test. See below.
> {
> for (i = start; i <= (start + count) && source[i] != '\0'; i++)
> {
> result [i] = source [i];
So if start is 17, i starts at 17 and this does result[17] =
source[17]. Is that what you want?
> }
> result [i + 1] = '\0';
> }
> else
> {
Here we know that count <= string_length(source) but that's not really
very useful to know. If the length is 100 and start is 99 even a count
of 10 goes wrong.
You mgith as well copy the characters you want and alway check to see if
the string has run out (i.e. check for the null). Counting them first
and then doing two different things based on that count is just a waste
of time.
> for (i = start; i <= (start + count); i++)
> {
> result [i] = source [i];
> }
> result [i + 1] = '\0';
> }
Presumably you intended to "return result;" here. Eeven if you did
this, it would not return the array because C functions can't return
arrays. It would, instead, return a pointer to the local array
(technically called an object with automatic storage duration) and you
should never do that because the array is about to disappear.
> }
<snip>
--
Ben.
[toc] | [prev] | [next] | [standalone]
| From | Alla _ <modelling.data@gmail.com> |
|---|---|
| Date | 2015-10-14 08:14 -0700 |
| Message-ID | <df41466b-e5e8-4182-abf3-a59ae10b58b8@googlegroups.com> |
| In reply to | #72830 |
> > subword [] = substring (word, start_letter, count_number);
>
> You can't assign to an array in C, if that is what you are trying to do
> (that would look more like subword = substring(...) so maybe that's not
> what you are trying).
>
> Pretty much the only viable option here is to pass into substring a
> pointer to the (start of) the array into which the substring should be
> copied.
>
Unfortunately, I don't understand this part. I don't see
how this functions differs from the function in the below
program (copied from the book), which doesn't return
anything as well.
// Program to read lines of data
#include <stdio.h>
void read_line (char buffer [], int size);
int main(void)
{
int i, n;
char line [81];
for (i = 0; i < 3; i ++)
{
read_line (line, n);
printf ("%s\n\n", line);
}
return 0;
}
void read_line (char buffer [], int size)
{
char character;
int i = 0;
printf ("Enter a line of text, up to 80 characters. Hit enter when done:\n");
do
{
character = getchar();
buffer[i] = character;
i++;
}
while (character != '\n');
buffer[i - 1] = '\0'; // i - 1 because the index character was incremented one extra time inside the loop the last time it was executed
}
> <snip>
> > void substring (char source[], int start, int count)
> > {
> > int i;
> > char result [80];
>
> Why 80? You can't know know that 80 is enough, but if you've picked a
> size for an array, make sure you check that it is enough. Either refuse
> to do anything if count >= 80, or only put a maximum of 79 characters
> and a null into it.
>
The book says that 80 is a standard width of the terminal :)
Actually, 80 is my mistake, corrected it to 81 to account for
a null character.
> > if (count > string_length (source))
>
> This is not a useful test. See below.
>
> > {
> > for (i = start; i <= (start + count) && source[i] != '\0'; i++)
> > {
> > result [i] = source [i];
>
> So if start is 17, i starts at 17 and this does result[17] =
> source[17]. Is that what you want?
>
> > }
> > result [i + 1] = '\0';
> > }
> > else
> > {
>
> Here we know that count <= string_length(source) but that's not really
> very useful to know. If the length is 100 and start is 99 even a count
> of 10 goes wrong.
>
>
Corrected :)
int i;
char result [81];
if (count > string_length (source))
{
for (i = start - 1; i <= (start - 1 + count) && source[i] != '\0'; i++)
{
result [i] = source [i];
}
result [i + 1] = '\0';
}
else if (count < string_length (source) && start >= 1 && start <= (length - count))
{
for (i = start - 1; i <= (start - 1 + count); i++)
{
result [i] = source [i];
}
result [i + 1] = '\0';
}
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2015-10-14 11:23 -0700 |
| Message-ID | <lnoag18g33.fsf@kst-u.example.com> |
| In reply to | #72844 |
Alla _ <modelling.data@gmail.com> writes:
>> > subword [] = substring (word, start_letter, count_number);
>>
>> You can't assign to an array in C, if that is what you are trying to do
>> (that would look more like subword = substring(...) so maybe that's not
>> what you are trying).
>>
>> Pretty much the only viable option here is to pass into substring a
>> pointer to the (start of) the array into which the substring should be
>> copied.
>>
> Unfortunately, I don't understand this part. I don't see
> how this functions differs from the function in the below
> program (copied from the book), which doesn't return
> anything as well.
[snip]
> void read_line (char buffer [], int size);
That read_line function doesn't directly return anything, but it does
pass information back to the caller via the object pointed to by the
`buffer` parameter. Your substring function has three parameters (and
no return value), none of which are used to pass information back to the
caller.
BTW, the parameter declaration `char bufer[]` is equivalent to
`char *buffer`, which is the way I'd write it.
You can't directly return an array value from a function. There are
several ways to do so indirectly:
- Return a pointer to (the first element of) a static array (this limits
the size of the array and clobbers the result when the function is
called again).
- Return a pointer to (the first element of) an array allocated with
malloc() (this requires the caller to deallocate the memory when it's
no longer needed).
- Require the caller to pass in a pointer to memory in which the result
will be stored, along with another parameter specifying the size (this
requires the caller to allocate memory, and to decide how much is
enough).
Other techniques are possible, but these are probably the most common.
There are language that let you return array values directly. Most of
them are implemented in C. 8-)}
[...]
> The book says that 80 is a standard width of the terminal :)
> Actually, 80 is my mistake, corrected it to 81 to account for
> a null character.
That's funny, I'm typing this into a terminal emulator whose current
width is 211 columns.
Even if you assume an 80-column terminal, it's still possible to enter
more than 80 characters on a line. As long as you cleanly handle long
lines without blowing up, you're ok. You can worry about handling
arbitrarily long input lines later.
[...]
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2015-10-14 21:22 +0100 |
| Message-ID | <871tcx9p4o.fsf@bsb.me.uk> |
| In reply to | #72844 |
Alla _ <modelling.data@gmail.com> writes:
>> > subword [] = substring (word, start_letter, count_number);
>>
>> You can't assign to an array in C, if that is what you are trying to do
>> (that would look more like subword = substring(...) so maybe that's not
>> what you are trying).
>>
>> Pretty much the only viable option here is to pass into substring a
>> pointer to the (start of) the array into which the substring should be
>> copied.
>>
> Unfortunately, I don't understand this part. I don't see
> how this functions differs from the function in the below
> program (copied from the book), which doesn't return
> anything as well.
<snip>
> void read_line (char buffer [], int size);
Indeed not. This function does exactly what I'm saying you need to do.
Here, buffer is a pointer to the start of an array of char. The
function fill the array with data read from the input stream.
You substring function needs another parameter which will be a pointer
to the array where it should copy the character of the requested
sub-string.
<snip>
>> > void substring (char source[], int start, int count)
>> > {
>> > int i;
>> > char result [80];
>>
>> Why 80? You can't know know that 80 is enough, but if you've picked a
>> size for an array, make sure you check that it is enough. Either refuse
>> to do anything if count >= 80, or only put a maximum of 79 characters
>> and a null into it.
>>
> The book says that 80 is a standard width of the terminal :)
> Actually, 80 is my mistake, corrected it to 81 to account for
> a null character.
OK, so you've explained why you pick that number (and I knew that too to
be honest -- it was a rhetorical question) but do you understand the
rest? It's very important to know why it's wrong to ignore an array's
size.
>
>> > if (count > string_length (source))
>>
>> This is not a useful test. See below.
>>
>> > {
>> > for (i = start; i <= (start + count) && source[i] != '\0'; i++)
>> > {
>> > result [i] = source [i];
>>
>> So if start is 17, i starts at 17 and this does result[17] =
>> source[17]. Is that what you want?
>>
>> > }
>> > result [i + 1] = '\0';
>> > }
>> > else
>> > {
>>
>> Here we know that count <= string_length(source) but that's not really
>> very useful to know. If the length is 100 and start is 99 even a count
>> of 10 goes wrong.
>>
>>
> Corrected :)
> int i;
> char result [81];
>
> if (count > string_length (source))
> {
> for (i = start - 1; i <= (start - 1 + count) && source[i] != '\0'; i++)
> {
> result [i] = source [i];
> }
> result [i + 1] = '\0';
> }
> else if (count < string_length (source) && start >= 1 && start <= (length - count))
> {
> for (i = start - 1; i <= (start - 1 + count); i++)
> {
> result [i] = source [i];
> }
> result [i + 1] = '\0';
> }
No, not corrected, just changed!
There's a lot more wrong with this version than the previous one, but
picking at it like a crow at road kill won't help anyone.
Here's another way to think about this where you won't be side-tracked
by the source length. You are sitting opposite me at a table. I have a
stack of playing cards and I ask you to put the 6 cards starting with
the 3rd onto the table in front of you. You can ask me for the next
card, but that's all. Every time you do I give you the next card or I
hold my hand up and say "null -- there is no next card". How do you
proceed?
--
Ben.
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.c
csiph-web