calculate value between two strings

C

Chad

Chad said:
void calculate(char *value, char first[], char second[])
{
  char difference = 0;
  char delta = 0;
  for( ;*first && *second; first++,second++) {
    difference = *first - *second;
    delta  = delta * 26 + difference;
  }
  *value = delta;
}
Wouldn't it be more convenient to have the function return the result
rather than assigning it via a pointer parameter?
A lot of the engineers at Lawrence Berkeley National Laboratory use
this method. I guess in my case, it's monkey see, monkey do. I don't
know if there is a formal computer science name to this technique or
if this is just some kind of strange Berkeley thing.

A common style is to have functions return a result that indicates
whether they succeeded or not, which means that the actual result has to
be communicated via a pointer argument.  For example, a square root
function in this style might look something like this:

    int square_root(double *result, double x) {
        if (x < 0.0) {
            return BAD_ARGUMENT;
        }
        else {
            *result = sqrt(x);
            return OK;
        }
    }

My guess is that that's what's going on at LBNL, and you've
misunderstood it (it doesn't make much sense for a void function to be
written this way).

[...]

Later on today, when I get home from work, I'll try and find some of
the C code from LBNL that uses this type of programming style.
 
C

Chad

Let's being the next round of below average C code. I guess I just
wanted to prove to myself that I can write C code without having to
resort to google or any kind of computer programming book for help.
With that, here is my attempt to attack the case when the input
strings aren't of equal length...

[cdalten@localhost oakland]$ more sub2.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void calculate_el(char *value, char first[], char second[])
{
char difference = 0;
char delta = 0;

for( ;*first && *second; first++,second++) {
difference = *first - *second;
delta = delta * 26 + difference;
}
*value = delta;
}

void calculate_ul(char *value, char first[], char second[], char
max[], \
size_t f_len, size_t s_len)
{
size_t l_diff;

if ( f_len > s_len) {
l_diff = f_len - s_len;
strncat(second, max ,l_diff);
} else {
l_diff = s_len - f_len;
strncat(first, max, l_diff);
}

calculate_el(value, first, second);
}

int main(void)
{
char first[BUFSIZ];
char second[BUFSIZ];
size_t f_len, s_len, max_value;
char value;

char
max[]="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
max_value = strlen(max);

printf("Enter the first string: ");
fflush(stdout);
if (scanf("%s", first) == 1) {
f_len = strlen(first);
if (f_len > max_value) {
fprintf(stderr, "The first input string is too long\n");
exit(1);
}
} else {
fprintf(stderr, "Try again\n");
}

printf("Enter the second string: ");
fflush(stdout);
if (scanf("%s", second) == 1) {
s_len = strlen(second);
if (s_len > max_value) {
fprintf(stderr, "The second input string is too long\n");
exit(1);
}
} else {
fprintf(stderr, "Try again\n");
}

if (f_len == s_len) {
calculate_el(&value, first, second);
printf("The difference between %s - %s is %d\n", first, second,
value);
} else {
calculate_ul(&value, first, second, max, f_len, s_len);
printf("The difference between %s - %s is %d\n", first, second,
value);
}

exit(1);
}
[cdalten@localhost oakland]$ gcc -Wall -Wextra sub2.c -o sub2
[cdalten@localhost oakland]$ ./sub2
Enter the first string: aaa
Enter the second string: aaa
The difference between aaa - aaa is 0
[cdalten@localhost oakland]$ ./sub2
Enter the first string: aad
Enter the second string: aaa
The difference between aad - aaa is 3
[cdalten@localhost oakland]$ ./sub2
Enter the first string: abc
Enter the second string: aaa
The difference between abc - aaa is 28
[cdalten@localhost oakland]$ ./sub2
Enter the first string: a
Enter the second string: abc
The difference between aaa - abc is -28
[cdalten@localhost oakland]$ ./sub2
Enter the first string: abc
Enter the second string: a
The difference between abc - aaa is 28
[cdalten@localhost oakland]$ ./sub2
Enter the first string:
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
The first input string is too long
[cdalten@localhost oakland]$ ./sub2
Enter the first string: b
Enter the second string:
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
The second input string is too long
[cdalten@localhost oakland]$
 
C

Chad

Let's being the next round of below average C code. I guess I just
wanted to prove to myself that I can write C code without having to
resort to google or any kind of computer programming book for help.
With that, here is my attempt to attack the case when the input
strings aren't of equal length...

I think the next time I'm drunk, I'm going to configure my editor so
like, when I copy and paste from my editor to comp.lang.c via the
google web interface, the code formatting will stay intact.
 
K

Keith Thompson

Chad said:
I think the next time I'm drunk, I'm going to configure my editor so
like, when I copy and paste from my editor to comp.lang.c via the
google web interface, the code formatting will stay intact.

Next time you're drunk, *unplug your computer*.
 
B

Barry Schwarz

Let's being the next round of below average C code. I guess I just
wanted to prove to myself that I can write C code without having to
resort to google or any kind of computer programming book for help.
With that, here is my attempt to attack the case when the input
strings aren't of equal length...

[cdalten@localhost oakland]$ more sub2.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void calculate_el(char *value, char first[], char second[])
{
char difference = 0;
char delta = 0;

for( ;*first && *second; first++,second++) {
difference = *first - *second;
delta = delta * 26 + difference;
}
*value = delta;
}

void calculate_ul(char *value, char first[], char second[], char
max[], \

What purpose do you think the \ serves? What would be different if
you left it out?
size_t f_len, size_t s_len)
{
size_t l_diff;

if ( f_len > s_len) {
l_diff = f_len - s_len;
strncat(second, max ,l_diff);

What makes you think that in general it is safe to append data to the
caller's array?
} else {
l_diff = s_len - f_len;
strncat(first, max, l_diff);
}

calculate_el(value, first, second);
}

int main(void)
{
snip

exit(1);
}

Why are you returning a non-portable value? Why is one normally not
associated with success?

snip
[cdalten@localhost oakland]$ ./sub2
Enter the first string: b
Enter the second string:
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
The second input string is too long
[cdalten@localhost oakland]$

It is a shame you didn't try to b and aaa to see the folly of trying
to store the result in a char.
 
C

Chad

Let's being the next round of below average C code. I guess I just
wanted to prove to myself that I can write C code without having to
resort to google or any kind of computer programming book for help.
With that, here is my attempt to attack the case when the input
strings aren't of equal length...
[cdalten@localhost oakland]$ more sub2.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void calculate_el(char *value, char first[], char second[])
{
 char difference = 0;
 char delta = 0;
 for( ;*first && *second; first++,second++) {
   difference = *first - *second;
   delta  = delta * 26 + difference;
 }
 *value = delta;
}
void calculate_ul(char *value, char first[], char second[], char
max[], \

What purpose do you think the \ serves?  What would be different if
you left it out?

I used the '\' character because the line wrap feature on my editor
doesn't play well with other editors line wrap feature.
What makes you think that in general it is safe to append data to the
caller's array?

I don't . What's a better method?
Why are you returning a non-portable value?  Why is one normally not
associated with success?

Because I was too lazy to type 'EXIT_FAILURE'.
 
B

Barry Schwarz

snip
void calculate_ul(char *value, char first[], char second[], char
max[], \

What purpose do you think the \ serves?  What would be different if
you left it out?

I used the '\' character because the line wrap feature on my editor
doesn't play well with other editors line wrap feature.

The point I was trying to make was that you don't need to concatenate
lines when the break occurs between tokens. You could just as easily
have typed
void calculate_ul(char *value,
char first[],
...
size_t s_len)
with no \ in sight and achieved the same result. The compiler will
strip out irrelevant white space.
I don't . What's a better method?

Either allocate or define an array of sufficient size and
copy/concatenate into that.
Because I was too lazy to type 'EXIT_FAILURE'.

Why would you use EXIT_FAILURE when the program worked successfully?
If you don't want to type EXIT_SUCCESS, 0 is guaranteed to have the
same effect.
 
B

Ben Bacarisse

Chad said:
void calculate_el(char *value, char first[], char second[])
{
 char difference = 0;
 char delta = 0;
 for( ;*first && *second; first++,second++) {
   difference = *first - *second;
   delta  = delta * 26 + difference;
 }
 *value = delta;
}
  size_t l_diff;
 if ( f_len > s_len) {
   l_diff = f_len - s_len;
   strncat(second, max ,l_diff);

What makes you think that in general it is safe to append data to the
caller's array?

I don't . What's a better method?

It's better to avoid having to alter or copy either string. I'd do
this:

long long str_diff(const char *s1, const char *s2)
{
const char *e1 = strchr(s1, 0);
const char *e2 = strchr(s2, 0);
long long diff = 0;
for (long long p = 1; e1 > s1 || e2 > s2; p *= 26)
diff += ((e1 == s1 ? 'a' : *--e1) - (e2 == s2 ? 'a' : *--e2)) * p;
return diff;
}

I.e. working backwards and faking the presumed leading 'a's.

<snip>
 
F

FredK

[snip]


Wouldn't it be more convenient to have the function return the result
rather than assigning it via a pointer parameter?

|A lot of the engineers at Lawrence Berkeley National Laboratory use
|this method. I guess in my case, it's monkey see, monkey do. I don't
|know if there is a formal computer science name to this technique or
|if this is just some kind of strange Berkeley thing.

It is not an uncommon convention in some programming environments that the
return from all procedure calls is a status code (or none if there is no
meaningful status).
 
C

Chad

[snip]



Wouldn't it be more convenient to have the function return the result
rather than assigning it via a pointer parameter?

|A lot of the engineers at Lawrence Berkeley National Laboratory use
|this method. I guess in my case, it's monkey see, monkey do. I don't
|know if there is a formal computer science name to this technique or
|if this is just some kind of strange Berkeley thing.

It is not an uncommon convention in some programming environments that the
return from all procedure calls is a status code (or none if there is no
meaningful status).

And in retrospect, I guess I would use fgets() instead of scanf().
Maybe something like the following...

[cdalten@localhost oakland]$ more getin.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX 10
int main(void)
{
char *buf;
char first[MAX];
char second[MAX];

printf("Input the first string:");
fflush(stdout);
if (fgets(first, MAX, stdin) != NULL) {
if (strlen(first) + 1 >= MAX) {
fprintf(stderr, "The first string is too long\n");
exit(EXIT_FAILURE);
} else if ((buf = strchr(first, '\n')) != NULL) {
*buf = '\0';
printf ("The first string is: %s\n", first);
}
}

printf("Input the second string:");
fflush(stdout);
if (fgets(second, MAX, stdin) != NULL) {
if (strlen(second) + 1 >= MAX) {
fprintf(stderr, "The second string is too long\n");
exit(EXIT_FAILURE);
} else if ((buf = strchr(second, '\n')) != NULL) {
*buf = '\0';
printf ("The second string is: %s\n", second);
}
}

exit(EXIT_SUCCESS);
}
[cdalten@localhost oakland]$ gcc -Wall -Wextra getin.c -o getin
[cdalten@localhost oakland]$ ./getin
Input the first string:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
The first string is too long
[cdalten@localhost oakland]$ ./getin
Input the first string:a
The first string is: a
Input the second string:b
The second string is: b
[cdalten@localhost oakland]$ ./getin
Input the first string:a
The first string is: a
Input the second
string:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
The second string is too long
[cdalten@localhost oakland]$
 
N

Nick Keighley

Does the order matter in this case?

yes. Assuming you expect the fflush() to be forcing the prompt to
appear before the scanf() tries to do the read. If you think the
fflush() is doing something to the input then you are in a state of
sin...

Oh, and scanf() with a %s format specifier is morally equivalent to
gets().

There is a special circle in hell reserved for such programmers.
Probably involves old COBOL.
 
N

Nick Keighley

Chad said:
Of course it does.  On some systems, your printf output will not be
visible until the fflush executes.  On those systems, your user will
not know why the system has stopped.
I don't know if the OP is still reading this, but how about something
like the following (for case 1)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void calculate(char *value, char first[], char second[])
{
  char difference = 0;
  char delta = 0;
  for( ;*first && *second; first++,second++) {
    difference = *first - *second;
    delta  = delta * 26 + difference;
  }
  *value = delta;
}

You are still returning a char.  That unlikely to be able to represent
the result for everything but a few pairs of string.
A lot of the engineers at Lawrence Berkeley National Laboratory use
this method. I guess in my case, it's monkey see, monkey do. I don't
know if there is a formal computer science name to this technique or
if this is just some kind of strange Berkeley thing.

It's worth thinking about Keith's question.  Another way to think about
the same thing is this: what *would* make you write a function that
returns the result rather than using a pointer parameter?  If the answer
is "nothing", why do programming languages have value-returning
functions at all?  If you *can* think of reasons to return a value, why
do they not apply in this case?

If you can't say *why* the good folks at LBL write their programs the
way they do, you can't draw any lessons from their code.  Learning by
copying code you don't understand is slow and error prone.

one possible reason is the return value is used as an error code (of
course Chad didn't do this)
 
B

Barry Schwarz

io_x said:
io_x said:
"John Green" <[email protected]> ha scritto nel messaggio
Hi,

I would like to calculate the value between two strings. For example:
abc-aaa would be 29.

I tried:
printf("abc-aaa = %d\n","abc"-"aaa");

in the fly

/*-1 for error */
unsigned value(char* a)
{int i;
unsigned tot;

if(a==0) return -1;
for(i=0, tot=0; i>=0 && a; ++i)
{tot+=a;
if((int)tot<0) return -1;


Are there systems where tot+=a overflow tot and tot>0?
i think not


Think instead. If tot+=a happens to exceed UINT_MAX, the resulting
value in tot will still be non-negative. So the answer to your
question is: Yes, every C system in the world as long as the sum is
not exactly equal to UINT_MAX+1.
the same for i
the wrost result is some seg fault for the overflow

Hardly. By far a worse result is to produce a garbage value and have
your program blissfully proceed without realizing there is a problem.
 

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
474,079
Messages
2,570,575
Members
47,207
Latest member
HelenaCani

Latest Threads

Top