Find value of some key

A

arnuld

Program works fine. Any improvements you can advise ?


/* A simple C program to find the value of a key inside an array. Array
has a unique key then its unique value next to it after
* a colon and space. Every key: value is separated by a newline. We
have to write a program to find and save the value if we
* pass it the key.
*
* VERSION 0.0
*/


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

enum { SIZE_VALUE = 20 };


char* get_value(const char*, const char*, char*);

int main(void)
{
const char* table = "OS: Linux\n compiler: gcc\n text-editor: Emacs\n
mentor: comp.lang.c\n";
char found_value[SIZE_VALUE] = {0};
const char* key = "arnuld";

printf("Table:\n %s", table);

printf("------------------------------\n\n");

if(get_value(table, key, found_value)) printf("%s = %s\n", key,
found_value);

return 0;
}



char* get_value(const char* t, const char* k, char* f)
{
int f_idx;
char* p = NULL;
size_t len_of_key = strlen(k);

/* printf("len_of_key: %lu\n", (unsigned long) len_of_key); */
p = strstr(t, k);

if(NULL == p)
{
printf("IN: %s: No Match for key\n", __func__);
return p;
}


/* It actually is: p = p + (len_of_key - 1) but we have 1 colon and 1
space before the value, hence + 2 to it */
p += len_of_key + 1;

for(f_idx = 0; *p != '\n'; ++p, ++f_idx)
{
f[f_idx] = *p;
}

/* printf("value: %s\n", f); */
return f;
}




--,
www.lispmachine.wordpress.com
my email is @ the above blog.
 
I

Ike Naar

Program works fine.

Are you sure?
Any improvements you can advise ?
[...]
char* get_value(const char* t, const char* k, char* f)
{
int f_idx;
char* p = NULL;
size_t len_of_key = strlen(k);

/* printf("len_of_key: %lu\n", (unsigned long) len_of_key); */
p = strstr(t, k);

Here you can go wrong. Consider what happens with the following table:

OS: experimentorLinux
compiler: gcc
text-editor: Emacs
mentor: comp.lang.c

If you search for the key "mentor", you will not find it on the
last line, as intended, but on the first line instead, and it
will produce the corresponding value "inux" instead of the
expected "comp.lang.c"
 
A

arnuld

Here you can go wrong. Consider what happens with the following table:

OS: experimentorLinux
compiler: gcc
text-editor: Emacs
mentor: comp.lang.c

If you search for the key "mentor", you will not find it on the last
line, as intended, but on the first line instead, and it will produce
the corresponding value "inux" instead of the expected "comp.lang.c"


How is this 2nd version:


/* A simple C program to find the value of a key inside an array. Array
has a unique key then its unique value next to it after
* a colon and space. Every "key: value" is separated by a newline. We
have to write a program to find and save the value if we
* pass it the key.
*
* VERSION 0.1
*
*/


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

enum { SIZE_VALUE = 20 };


char* get_value(const char*, const char*, char*);

int main(void)
{
const char* table = "OS: experimentorLinux\n compiler: gccmentor\n text-
editor: Emacs\n mentor: comp.lang.c\n";
char found_value[SIZE_VALUE] = {0};
char found_value2[SIZE_VALUE] = {0};
char found_value3[SIZE_VALUE] = {0};
const char* key = "mentor";
const char* key2 = "NotPresent";
const char* key3 = "OS";


printf("Table:\n %s", table);

printf("------------------------------\n\n");

if(get_value(table, key, found_value)) printf("%s = %s\n", key,
found_value);
if(get_value(table, key2, found_value2)) printf("%s = %s\n", key2,
found_value2);
if(get_value(table, key3, found_value3)) printf("%s = %s\n", key3,
found_value3);

return 0;
}



char* get_value(const char* t, const char* k, char* f)
{
int f_idx;
char* p = NULL;
size_t len_of_key = strlen(k);

while(1)
{
p = strstr(t, k);

if(NULL == p)
{
printf("IN: %s at %d: No Match for key\n", __func__, __LINE__);
return p;
}

p += len_of_key; /* It actually is: p = p + (len_of_key - 1) but
we have 1 colon after key */

if(*p == ':' && *(p+1) == ' ' )
{
++p; /* Removing the next space after colon */
for(f_idx = 0; *p != '\n'; ++p, ++f_idx)
{
f[f_idx] = *p;
}

break;
}
else
{
t = p;
}
}

return f;
}

====================== OUTPUT ================================
[arnuld@dune programs]$ gcc -ansi -pedantic -Wall -Wextra find-value.c
[arnuld@dune programs]$ ./a.out
Table:
OS: experimentorLinux
compiler: gccmentor
text-editor: Emacs
mentor: comp.lang.c
------------------------------

mentor = comp.lang.c
IN: get_value at 55: No Match for key
OS = experimentorLinux
[arnuld@dune programs]$
 
A

arnuld

p += len_of_key; /* It actually is: p = p + (len_of_key - 1) but
we have 1 colon after key */

if(*p == ':' && *(p+1) == ' ' )
{
++p; /* Removing the next space after colon */ for(f_idx = 0;

Its p = p + 2 actually :)
 
M

Mark Bluemel

Program works fine.

I doubt it.
Any improvements you can advise ?

Your data is effectively a file containing a number of records, each
divided into a number of fields - why doesn't your design reflect
that?

Get a record/line at a time from your data source, extract the first
field and compare it to your desired value.
 
I

Ike Naar

How is this 2nd version:

A little better, but it has similar problems like the previous version had.
Consider this table:

elephant: big
ant: tiny
ladybug: scary

If you search for "ant", you'll find "elephant".
 
V

Vincenzo Mercuri

arnuld said:
Program works fine. Any improvements you can advise ?


/* A simple C program to find the value of a key inside an array. Array
has a unique key then its unique value next to it after
* a colon and space. Every key: value is separated by a newline. We
have to write a program to find and save the value if we
* pass it the key.
*
* VERSION 0.0
*/

Hi,
i thought about a personal solution,
i hope it will help you getting your code work out (gcc -std=c99):

#include <stdio.h>
#include <string.h>

char* get_value(const char* [], const char* [], char*);
void print_table(const char* [], const char* []);

char* key1 = "mentor";
char* key2 = "OS";
char* key3 = "ant";

int main(void){


const char* fields[] = {"OS",
"compiler",
"text-editor",
"mentor", NULL};

const char* values[] = {"Linux",
"gcc",
"Emacs",
"comp.lang.c", NULL};

print_table(fields, values);

(void) get_value(fields, values, key1);
(void) get_value(fields, values, key2);
(void) get_value(fields, values, key3);

return 0;
}

void print_table(const char* f[], const char* v[]){

printf("\nTable:\n");
printf("---------------------------\n");

for(int i = 0; f; i++)
printf("%s: %s\n", f, v);

printf("---------------------------\n\n");

}


char* get_value(const char* f[], const char* v[], char* k){

int found = 0;

for(int i = 0; f; i++){

if ( !strcmp(f, k) ) {
printf("%s = %s\n\n", f, v);
found = 1;
break;
}
}

if ( !found )
printf("IN: %s at %d: No Match for key\n\n", \
__func__, __LINE__);

return found ? k : NULL ;
}
 
D

Dann Corbit

{snippity-snip}

The fundamental approach is bad.

Make a skiplist and you can have a generic, ordered container. Or make
a hash table and you will have ultra-fast equality searching.

When faced with a problem, I think that the goal should be to solve the
problem in a very useful way. Think of being able to reuse what you do
later. Anything worth doing is worth doing well.

If, on the other hand, you want something ultra-simple, then make an
array of structs and do a linear search. If you group your data and key
together in a struct, it will simplify your operations.

If you wanted to make a fairly generic list, you could use void pointers
both to key and data and then have callback interpretation functions to
actually fiddle with the data and interpret the key.

If you have a list that consists only of keys and not data, then you are
faced with a question:
"Will I search the list over and over or only a very few times?"
If you are going to search the list over and over, then you have another
question:
"Will the list grow and shrink or will it stay the same size?"

If the list will only be searched once or a very tiny number of times,
then just do a linear search. A search is O(N) while ordering the data
is O(N*log(N)) so you will have to do log(N) searches before ordering
the data becomes cheaper.

If you are going to search over and over then if the list stays the same
size just sort it and do bsearch() to find items. If it grows and/or
shrinks then use a data structure like a skiplist or an avl tree or a
hash table or some such. Hash tables are best if you never do range
searches (think 'dictionary' where the only operation is equality
search). If you need ordered lists or range checks then use skiplist,
avl tree, red black tree or some such thing.

So the first part of the problem is to clearly specify the problem.
Once the problem is set in stone and all the parameters are clearly
known, then the rest of the system falls out all by itself.
 
C

Chad

{snippity-snip}

The fundamental approach is bad.

Make a skiplist and you can have a generic, ordered container.  Or make
a hash table and you will have ultra-fast equality searching.

When faced with a problem, I think that the goal should be to solve the
problem in a very useful way.  Think of being able to reuse what you do
later.  Anything worth doing is worth doing well.

If, on the other hand, you want something ultra-simple, then make an
array of structs and do a linear search.  If you group your data and key
together in a struct, it will simplify your operations.

If you wanted to make a fairly generic list, you could use void pointers
both to key and data and then have callback interpretation functions to
actually fiddle with the data and interpret the key.

If you have a list that consists only of keys and not data, then you are
faced with a question:
"Will I search the list over and over or only a very few times?"
If you are going to search the list over and over, then you have another
question:
"Will the list grow and shrink or will it stay the same size?"

If the list will only be searched once or a very tiny number of times,
then just do a linear search.  A search is O(N) while ordering the data
is O(N*log(N)) so you will have to do log(N) searches before ordering
the data becomes cheaper.

If you are going to search over and over then if the list stays the same
size just sort it and do bsearch() to find items.  If it grows and/or
shrinks then use a data structure like a skiplist or an avl tree or a
hash table or some such.  Hash tables are best if you never do range
searches (think 'dictionary' where the only operation is equality
search).  If you need ordered lists or range checks then use skiplist,
avl tree, red black tree or some such thing.

So the first part of the problem is to clearly specify the problem.  
Once the problem is set in stone and all the parameters are clearly
known, then the rest of the system falls out all by itself.

I don't think homeboy is capable of actually doing something like what
you suggest. You don't believe it? Let me take a quote from his
blog...

"So I don’t have mathematical skills, I do not have much IQ and all
the technical things that programmers like Richard Stallman, Linus
Torvalds, Joel Spolsky, Paul Graham and Eric S. Raymond talk about,
the things that lie at the core of UNIX way, just sweep above my head,
so I decided not to waste the resources."

Chad
 
E

Eric Sosman

[...]
So the first part of the problem is to clearly specify the problem.
Once the problem is set in stone and all the parameters are clearly
known, then the rest of the system falls out all by itself.

I don't think homeboy is capable of actually doing something like what
you suggest. You don't believe it? Let me take a quote from his
blog...

"So I don’t have mathematical skills, I do not have much IQ and all
the technical things that programmers like Richard Stallman, Linus
Torvalds, Joel Spolsky, Paul Graham and Eric S. Raymond talk about,
the things that lie at the core of UNIX way, just sweep above my head,
so I decided not to waste the resources."

Big f-ing deal. Not everyone is Stallman or Knuth or Ritchie, and
this is both normal and predictable. If programming were something that
could be done only by the Duffs, Thompsons, and Bentleys, there would be
precious little programming done -- and very little of it "precious."

Some thirty-mumble years ago the word "engineer" started to creep
into my job titles, but I've known all along that it was undeserved.
Engineers have handbooks that tell them the tensile strength of nickel-
molybdenum-plated high-carbon steel reinforcing rods, with and without
fibre admixtures in the surrounding concrete, in radon-rich atmospheres
of the following concentrations: A,B,C,... What's more, engineers know
how to apply what they find in these handbooks! (Mere mortals don't.)
But software "engineers" are at the developmental level of alchemists,
each convinced that his way is The Philosopher's Stone that will solve
all the problems. That sort of "engineering" is not so much a dead end
as an infinite bifurcation into tiny alleys that grow ever narrower
until further passage becomes impossible.

A few people exist who can rise above this sink of self-indulgent
mediocrity, and we should all be thankful for them. But for the rest
of us, the principal hope for a better tomorrow lies in finding ways to
write good programs *without* being geniuses, that is, in the founding
of a true engineering discipline for computer systems. Establishing
that discipline will take the work of genius -- no, of geniuses -- but
if the end result is to be economically and socially viable it *will*
offer ways for "by the book" programmers to be effective.

No endeavor that *requires* genius at all times can long survive.

So, Chad: Pray give us a few links to *your* Linux, *your* emacs,
*your* TeX, *your* -- oh, Hell, *your* anything at all, that we may
judge its originality and inspiration, and then accept your denigration
of the efforts of an obvious beginner. We await your brilliant
response.
 
C

Chad

[...]
So the first part of the problem is to clearly specify the problem.
Once the problem is set in stone and all the parameters are clearly
known, then the rest of the system falls out all by itself.
I don't think homeboy is capable of actually doing something like what
you suggest. You don't believe it? Let me take a quote from his
blog...
"So I don t have mathematical skills, I do not have much IQ and all
the technical things that programmers like Richard Stallman, Linus
Torvalds, Joel Spolsky, Paul Graham and Eric S. Raymond talk about,
the things that lie at the core of UNIX way, just sweep above my head,
so I decided not to waste the resources."

     Big f-ing deal.  Not everyone is Stallman or Knuth or Ritchie, and
this is both normal and predictable.  If programming were something that
could be done only by the Duffs, Thompsons, and Bentleys, there would be
precious little programming done -- and very little of it "precious."

     Some thirty-mumble years ago the word "engineer" started to creep
into my job titles, but I've known all along that it was undeserved.
Engineers have handbooks that tell them the tensile strength of nickel-
molybdenum-plated high-carbon steel reinforcing rods, with and without
fibre admixtures in the surrounding concrete, in radon-rich atmospheres
of the following concentrations: A,B,C,...  What's more, engineers know
how to apply what they find in these handbooks!  (Mere mortals don't.)
But software "engineers" are at the developmental level of alchemists,
each convinced that his way is The Philosopher's Stone that will solve
all the problems.  That sort of "engineering" is not so much a dead end
as an infinite bifurcation into tiny alleys that grow ever narrower
until further passage becomes impossible.

     A few people exist who can rise above this sink of self-indulgent
mediocrity, and we should all be thankful for them.  But for the rest
of us, the principal hope for a better tomorrow lies in finding ways to
write good programs *without* being geniuses, that is, in the founding
of a true engineering discipline for computer systems.  Establishing
that discipline will take the work of genius -- no, of geniuses -- but
if the end result is to be economically and socially viable it *will*
offer ways for "by the book" programmers to be effective.

     No endeavor that *requires* genius at all times can long survive.

     So, Chad: Pray give us a few links to *your* Linux, *your* emacs,
*your* TeX, *your* -- oh, Hell, *your* anything at all, that we may
judge its originality and inspiration, and then accept your denigration
of the efforts of an obvious beginner.  We await your brilliant
response.

--

Have you ever followed some of the arnuld threads on this joint? With
that, I haven't written any kind of notable software. I'm just some 36
yr old assembly line worker at Kodak that barely made it through high
school. In between, I read comp.lang.c, comp.unix.programmer, and
comp.unix.shell, as opposed to say, watching TV or going with my co-
workers to the local bar to just "hang out".

I'm not a genius. I don't think I ever claimed to be one. Heck, there
days that I struggle to be slightly below average. Now I'm going back
to reading this forum, and asking questions, when I don't understand a
response. Hopefully I haven't alienated myself too much from the
regulars on here.
 
E

Eric Sosman

[...]
So, Chad: [...] We await your brilliant response.

Chad, I'd like to apologize for my tone at the close of this
message. I truly believe what I wrote about the need to move
beyond relying on geniuses, but there was no call for me to get
so snootily personal towards you. I'm sorry.
 
N

Nick Keighley

"arnuld" <[email protected]> ha scritto nel messaggionews:p[email protected]...

What does the key mean?

usually some form of unique identifier that identifies some data. Go
and read some database theory.
for me the key is the number that identify the struct
in one array it is the index "i"

yes, but not in his code if you'd bothered to look at it. He seems to
using "key" to mean a short string in this case
i find useful see one array of structs; it is fine
for search one element, and from the key identify the element

yes but that doesn't address his problem.
but not debugged it much,
so all you has to debug it for search errors

a much simpler method is to refrain from making any mistakes whilst
writing the code.
this should be standard C code
but if some of you prefer can mental see "P" -> "printf" etc etc

it is for this i'm one black sheep, i don't follow something
for example don't follow "one line one instructions" too
i don't see the advantage of that
i'm stupid?

I suggest you go and find a group of people who find your programming
style pleasing and talk to them.
#include <stdio.h>
#include <stdlib.h>
#define  W  while

<snip crap code>
 
M

Mark Bluemel

I doubt it.


Your data is effectively a file containing a number of records, each
divided into a number of fields - why doesn't your design reflect
that?

Get a record/line at a time from your data source, extract the first
field and compare it to your desired value.

Here's a simplistic version (I needed some distraction) which makes
more
sense to me...

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

enum { SIZE_VALUE = 20 };

char* get_value(const char* table, const char* key, char* buffer);

int main(int argc, char* argv[])
{
const char* table = "OS: Linux\n compiler: gcc\n"
" text-editor: Emacs\n mentor: comp.lang.c\n";
char* value;
char buffer[SIZE_VALUE];
int i;

printf("Table:\n %s", table);

printf("------------------------------\n\n");

for(i=1; i < argc; i++) {
char* key = argv;
if((value = get_value(table, key, buffer)) != NULL) {
printf("%s = %s\n", key, value);
} else {
printf("%s NOT FOUND\n",key);
}
}

return 0;
}

char *get_value(const char *table, const char *key, char *buffer) {
int keyLength = strlen(key);
char *current = table; /* beginning of the current line */
while(*current != '\0') {
/* look for the key at the start of the line */
if ((strncmp(key,current,keyLength) == 0)
/* followed by a ':' */
&& (current[keyLength] == ':')) {
/* skip over the key and ':' */
char *from = current + keyLength + 2;
/* copy to the end of the line */
char *to = buffer;
while(*from != '\n') {
*to++ = *from++;
}
*to = '\0';
return buffer;
}
/* not found (yet) */
/* move to next line */
while((*current != '\n') && (*current != '\0')) {
current++;
}
/* skip newline and leading spaces */
while((*current == ' ') || (*current == '\n')) {
current++;
}
}
return NULL;
}


And here's the output of a run of this version :-

$ ./arnuld OS mentor compiler text-editor banana
Table:
OS: Linux
compiler: gcc
text-editor: Emacs
mentor: comp.lang.c
------------------------------

OS = Linux
mentor = comp.lang.c
compiler = gcc
text-editor = Emacs
banana NOT FOUND
 
C

Chad

[...]
So, Chad: [...] We await your brilliant response.

     Chad, I'd like to apologize for my tone at the close of this
message.  I truly believe what I wrote about the need to move
beyond relying on geniuses, but there was no call for me to get
so snootily personal towards you.  I'm sorry.

It's all good. I'm just glad that you, along with Keith, take the time
to answer my questions.
 
V

Vincenzo Mercuri

Il 23/06/2010 21.46, io_x ha scritto:
yes it is crap
here the range is start..end-1 and not start..end
so i have to change all
but i'm tired so will remain all so
this is one exercise for the reader :)
hope not hurt too much :)

....is that a joke? Why this behaviour?
I think we all appreciate to get fun with code sometimes, but why
this try to prove yourself as some kind of a bizarre genius?
If this is your intent, you are unlikely able to do it.
I think there are some people here who would really have
enough skills to do better. If they only wanted.
So, even as a joke it is not well-made. We are all free to
use the style we prefer, but i think sometimes you persist
in showing off a bit of lack of regards about the readers.
Trying to be clear and showing our ideas in an intelligible manner
would be desirable by the most (hopefully).
And about your italian words in your code...I am italian too,
and i think i have to recall you that english is the lingua franca
in programming, and we should use it when talking to people overseas, so
we can all understand, appreciate and share new ideas.
Please don't continue with this self-destructive behaviour,
and try to let people appreciate your true abilities.

Regards
 
I

iC and iC++

I'm not a genius. I don't think I ever claimed to be one. Heck, there
days that I struggle to be slightly below average.

Good. now i can see whence your complex arises.
 
C

Chad

Good. now i can see whence your complex arises.

Huh? I'm not the one trying to learn about pointers from a book that I
was told not to use. Not only that, your grammar bites. Now go run
along and struggle with pointers. Not that the learning curve was that
sharp to begin with. But whatever.
 
C

Chad

Huh? I'm not the one trying to learn about pointers from a book that I
was told not to use. Not only that, your grammar bites. Now go run
along and struggle with pointers. Not that the learning curve was that
sharp to begin with. But whatever.

*but your grammar bites*
 

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

No members online now.

Forum statistics

Threads
473,954
Messages
2,570,116
Members
46,704
Latest member
BernadineF

Latest Threads

Top