CompuServe Thread

#Strings in C

42 messages in this thread
#44152From: ShraddhanNov 21, 1994 6:14 PM
Having yet again tried to get to grips with C, I have a little question for you old hands: How do I define in C (using DICE) the string which in assembler is: dc.b $9B,"0 p",0 If I use "\x9B0 p" I get the equivalent of $B0," p" with a warning that the hex value has more than two characters (i.e. the 9 has been ignored by DICE), and if I use "\x9B 0 p" I get the string $9B," 0 p" – i.e. with a superfluous space. If it makes any difference, I would like to #define the above string. Regards, Shraddhan (via AP from Hertfordshire, England)
#44158From: Steve AhlstromNov 22, 1994 12:51 AM
I don't do assembler. If you state your question in english maybe I can help.
#44205From: ShraddhanNov 23, 1994 10:57 AM
> If you state your question in English maybe I can help Right, given that I can define a string in C as, for example, "ABCD" – which a represents a pointer to the byte values 65, 66, 67, 68, 0 – I would like to know if there is a convenient way of representing a string which contains characters not directly accessible via the keyboard. My original example was a string containing the byte values 155, 48, 32, 112, 0 which corresponds to the character '\x9B' followed by the characters which comprise the C string "0 p" Now, the problem is that if I try to define the string as "\x9B0 p" I find that DICE objects to this, saying that I have too many digits. It takes the '0' character as being a third digit to the \x9B specification, rather than being the next valid ASCII character in the string. So, for example, "\x9B p" is correctly translated by DICE into the sequence 155, 32, 112, 0 whereas "\x9B0 p" becomes (after a warning) the sequence 176, 32, 112, 0 Finally, my question is: what is the simplest, most convenient way to get round the behaviour described above, so that I can enter arbitrary characters (expressed as hexadecimal numbers) into arbitrary strings (containing digits)? One way that works is to convert the whole lot into hex or octal characters. This, I find, is a pain, as my skills in ASCII -> octal conversion are not good. Another way is to specify the whole lot on a chracter-by-character basis, which is clumsy. Both these techniques are too prone to errors. ………………………………………………… While I have your attention, can I ask a second question on a totally different topic? I would like to create a look-up table of alternating pointers to strings and pointers to corresponding functions to be executed. What is the syntax for specifying such a table? The overall aim is to write a parser that looks at an input file, picks out a possible keyword at the start of a line, looks it up in the table, and if found, executes the appropriate function to interpret the remainder of the line. Many thanks for any help. Regards, Shraddhan (via AP from Hertfordshire, England)
#44221From: Peter WadeNov 23, 1994 4:49 PM
If your function returns a void and takes no parameters, you could use : struct function_entry { char *keyword ; /* keyword is a pointer to a string */ void ( *action ) ( void ) ; /* action is a pointer to a function */ } ; struct function_entry lookup_table [100] ; /* Table of 100 entries */ Change the void at the front if your funtion returns something, change the void in the brackets if it needs parameters. You can fill in the function entries by assigning to the name of a function without the brackets, e.g. : void process_start ( void ) ; /* Defined somewhere in the program */ lookup_table[0].action = process_start ; Then you can execute the function by putting the brackets after it, e.g.: lookup_table[0].action () ; /* Executes funtion through pointer */ I hope this is of help. Peter Wade Autopiloting from London, England
#44297From: ShraddhanNov 25, 1994 6:44 PM
Peter, Thanks for showing me how to create arrays of structures. I now have a little problem that has had me baffled for the last three hours, and I have discovered that it is to do with the use of EXTERN. I'm having some difficulty referring in one file to an array defined in another file. One file contains: struct Atom { char *_Name; APTR atom_Value; APTR atom_Next; }; struct Atom Object[] = { { "alpha" }, { "beta" }, { "gamma" }, }; /* …… to here */ The second file contiains: #define Value_Beta Object[1].atom_Value as a convenient way of referring to the value pointer of an array item. (I woould really like to be able to refer by name to something like 30 out of the 2500 or so memory locations used by the array.) However, when I try to use Value_Beta, I keep getting errors which imply that the structures in the array elements are not defined. I have tried the following two lines to no avail in the second file: extern struct Atom Object[]; extern Object[]; The code seems to compile with no problem if the two files are combined. Why won't the compiler (DICE) recognise that the array referred to in one file is defined in the other file? Regards, Shraddhan (via AP from Hertfordshire, England)
#44316From: Jim MaddoxNov 26, 1994 12:39 PM
Shraddhan – I don't know if this will help or not, but I had a similar experience while breaking up a large program in TurboC. I ended up having to put my struct definitions in a header file which I #included in every file that made up the project. In your case, struct.h would contain your Atom structure, your main program (or another header) could define the Object[] array, and your subprogram would include the lines "#include <struct.h>" and "extern struct Atom Object[];". – Jim, on AutoPilot!
#44333From: Peter WadeNov 27, 1994 9:41 AM
If I understand you rightly, you only have struct Atom { char *_Name; APTR atom_Value; APTR atom_Next; }; in the first file. Am I correct ? If this is the case then that is your problem. The compiler treats each .c file seperatly, it does not remember the declaration of struct Atom when it is on the second file. The line : extern struct Atom Object[] ; tells it that Object is an external array of struct Atom but it still does not know what a struct Atom actually is. The way round this is to take your "struct Atom { …" declaration out of the first file and put it into a header file, e.g. atom.h, then put the line: #include "atom.h" at the tope of both of your .c files. Keep the "struct Atom Object[] …" definition in your first file and use the line: extern struct Atom Object[]; in your second file. > Why won't the compiler (DICE) recognise that the array referred to in > one file is defined in the other file? C compilers treat each .c file they compile as a seperate operation even if they are on the same command line. That is why you have to #include all of the system header files into each file that uses them. You can use extern to tell it about an external variable which is a data type it already knows, but you have to include the structure declarations for any structures that you use. N.B. The difference between declaring a variable and defining it is that defining it creates the variable and allocates memory for it but declaring it just says what type it is. So : struct Atom Object[1000] ; /* This is a definition */ extern struct Atom Object[] ; /* This is a declaration */ This is worth remembering if you are reading textbooks on the subject. Well, that is probably longer than you were expecting. I hope it is of help. Happy Programming! Peter Wade Autopiloting from London, England
#44369From: Steve AhlstromNov 28, 1994 3:18 AM
Personally I'd typedef the structure def. -sja
#44379From: Peter WadeNov 28, 1994 5:58 PM
IMHO Its a matter of style. I've never got into the habbit of using typdefs, probably because they were not used much in the course where I learnt C. They do save typeing though (and forgetting to put the word struct in a definition is one of my commonest typos). It is also closer to the way C++ handles structs. Peter Wade Autopiloting from London, England
#44160From: Jim MaddoxNov 22, 1994 12:55 AM
Hmm. Maybe I can return your favor. 🙂 >> How do I define in C (using DICE) the string which in assembler is: >> dc.b $9b,"0 p",0 I'm not too sure about #defining it (or about DICE, as I use TurboC++), but if you were using an array, you might try: char string[] = { '\0x9b',"0 p",'\0' }; (Or char *string; whatever suits you better.) I suppose it wouldn't hurt to try this, though: #define STRING { '\0x9b',"0 p",'\0'} Or, you could create the aforementioned array and just do this: #define STRING *string Hope it helps. – Jim, on AutoPilot!
#44206From: ShraddhanNov 23, 1994 10:57 AM
Jim, I tried your suggestions, and got none of them to work 🙁 In the line: char string[] = { '\0x9b',"0 p",'\0' }; aren't you mixing up characters and strings? My current thinking is that there seems to be no easy, convenient solution. I _knew_ there was a reason why I hated C! 🙂 Regards, Shraddhan (via AP from Hertfordshire, England)
#44220From: Jim MaddoxNov 23, 1994 4:18 PM
I finally got it to work. Just do this: #define STRING "\x9b\x20 p" // dc.b $9b,"0 p",0 Or, you could find out which key combo produces a $9b character (on my PC it's the monetary cent sign) and use it instead of the '\x9b.' If converting the characters following the special characters is too much trouble, you could always write a program to parse your dc.b statements into #defines with hex or octal strings for you. (Or is that more trouble? Nah! <g>) – Jim, on AutoPilot!
#44235From: Jim MaddoxNov 24, 1994 1:20 AM
>> #define STRING "\x9b\x20 p" // dc.b $9b,"0 p",0 Oops. That should be "\x9b\x30 p".
#44293From: ShraddhanNov 25, 1994 6:14 PM
Jim, Thanks for your help. I've got it all sorted out now. > If converting the characters following the special characters is too > much trouble, you could always write a program to parse your dc.b > statements into #defines with hex or octal strings for you. (Or is > that more trouble? It seems to me that I can get DICE's VMake to run such a program for me, so it's an idea worth considering for the future. Alos, writing such a program would give me something to do when I get totally stuck next time and have to wait a few hours for help. 🙂 Regards, Shraddhan (via AP from Hertfordshire, England)
#44164From: Werner KazmierzakNov 22, 1994 1:43 AM
Shraddhan, dc.b $9B,"0 p",0 may be written as "/233/60/40/120" in C. – wkc – … via AP from Hamburg, Germany
#44207From: ShraddhanNov 23, 1994 10:57 AM
Werner, Thanks for your suggestion for writing the whole string in octal. I have used your suggestion, as it works, with the addition of a comment to show me what the string really is, as I find a string such as "\233\60\40\160" to be totally unpenetrable. Regards, Shraddhan (via AP from Hertfordshire, England)
#44256From: Werner KazmierzakNov 24, 1994 4:22 PM
Shraddan, I did suggest to use octals because this is compatible with K & R (first edition). The escape-sequence \x (and \v) was introduced later in ANSI-C, so there might be some portability problems on older systems. Of course, either using octal or hex, the problem is, that a digit that is following the expression will be interpreted to be a digit of the number itself. For portability reasons, integer numbers greater than 255 must be allowed to be assigned to a variable of type char, because sizeof(char) may be greater than 1 on some alien environment. – wkc – … via AP from Hamburg, Germany
#44296From: ShraddhanNov 25, 1994 6:44 PM
Werner, I can appreciate the logic of sticking to octal. I had just hoped that there might have been an easy way of avoiding the confusion between interpreting a digit as octal or hex, and interpreting it as an ASCII character. Oh well, I do have that bit of code sorted out well enough for the time being. Thanks. Regards, Shraddhan (via AP from Hertfordshire, England)
#44173From: Jim MaddoxNov 22, 1994 10:58 AM
Whoops…please disregard that last bit of information. I just tried it out on TCC and it didn't work. :l If #define STRING "\x9B0 p" almost works for you, you could try: #define STRING "\x9B\48 p" That, I should think, will solve the $9B0 -> $B0 problem. (But I wonder why none of this seemed to work on TurboC….) – Jim, on AutoPilot!
#44185From: Peter WadeNov 22, 1994 3:56 PM
The \48 won't work because \nn syntax expects the number to be in octal. I tried \48 with SAS C and it treated it as octal 4 followed by "8" since 8 is not an octal digit. \x30 or \60 should work. Peter Wade Autopiloting from London, England
#44192From: Jim MaddoxNov 22, 1994 6:33 PM
Oh. <g> I hadn't ever had that problem before…does a decimal use a \nnn syntax? You see, I have this looong header file filled with PC key combination names and their decimal character equivalents. I _really_ don't want to re-do it (have to see if I have to), but it's worked fine so far. I knew I should have left the line "I've never done this before" in…. – Jim, on AutoPilot!
#44222From: Peter WadeNov 23, 1994 4:49 PM
Kernighan and Ritchie (second edition) don't mention any way of specifying the character code in decimal, only hex and octal. Some compilers might have their own extensions to this but they would have to be different from \nnn otherwise the compiler would have no way to tell if \123 was decimal or octal (or they would not be compatible with ANSI C). Peter Wade Autopiloting from London, England
#44230From: Jim MaddoxNov 23, 1994 10:15 PM
That's what I was afraid of. 🙁 Oh, I just remembered…I didn't use the '\nnn' notation on the keydefs. I used integers, as in "#define ESC 27." So, I guess it's no loss; just something to avoid in the future. 🙂 (Who in the universe uses octal anyway?! <g>) – Jim, on AutoPilot!
#44321From: Malcolm O'BrienNov 26, 1994 8:30 PM
Jim, > (Who in the universe uses octal anyway?! <g>) CIS user IDs are octal numbers. 😉 Malcolm
#44331From: Jim MaddoxNov 27, 1994 2:16 AM
>> CIS user IDs are octal numbers. 😉 <gasp> I never thought of that! You know, I don't remember ever having seen an "8" in a user ID number (not that I ever paid that much attention anyway <g>). – Jim, on AutoPilot!
#44370From: Steve AhlstromNov 28, 1994 3:18 AM
Jim, Think DEC … user ids are more appropriately known as PPNs — programmer project numbers. -sja
#44327From: Brian BartlettNov 27, 1994 12:35 AM
Jim, the United States Navy, for one. The Harris 300 is all octal <g>.
#44343From: Eulogio (DJ) GarciaNov 27, 1994 3:16 PM
Yeah, it's what is known as a three-bit computer … DJ On AP from Queens, the thrill and excitement of the Big Apple Where a little paranoia keeps you healthy and sane …
#44346From: Marlene Zenker/SYSOPNov 27, 1994 3:41 PM
Harris 300? As in Harris Computer Systems? I've worked at Harris in the Security group for the last couple of years, and I've never even heard of that system. (Not surprisingly, I guess….They made a lot of different systems).
#44348From: Eulogio (DJ) GarciaNov 27, 1994 3:49 PM
I almost went to work for Harris in Melbourne, FL a long time ago. They had some neat phototypesetting stuff, plus computers and semiconductors, at the time. DJ On AP from Queens, the thrill and excitement of the Big Apple Where a little paranoia keeps you healthy and sane …
#44657From: Brian BartlettDec 6, 1994 1:21 AM
Steve, as I recall, the official Navy designation for the beast is the AN/UYK-62(V). Anyway, there were two different cases, but basically the same guts. One mainframe size, and one mini-case (for submarines). All octal, ECL, and actually quite speedy, if the program was written correctly (and some weren't!). PS: Sorry about delay, just got out of the hospital.
#44208From: ShraddhanNov 23, 1994 11:17 AM
Jim, And I'd been hoping that there was an easy answer to defining arbitrary strings. I _knew_ that I hated C, but had forgotten why. Thanks for your help. Regards, Shraddhan (via AP from Hertfordshire, England)
#44211From: Jim MaddoxNov 23, 1994 1:42 PM
Hey, I know! Just use the string "x0 p" and then change it to $9b"0 p" in the executable with NewZap! <g> Seriously, I'll work on that string thing and get back to you. – Jim, on AutoPilot!
#44184From: Peter WadeNov 22, 1994 3:56 PM
You have come across a problem wuth the way C handles hex character constants. According to Kernighan and Ritchie the \xnn syntax can have as many hex digits as you like. This means if you try and follow it with a character which is also a hex digit the compiler thinks it is part of the hex humber. You can get round this by coding the 0 as another hex constant. The space after the 0 is not a problem. Try : #define my_string "\x9B\x30 p" N.B. You don't need to include the final 0 because C string handling functions always assume a 0 at the end of a string. Peter Wade Autopiloting from London, England
#44209From: ShraddhanNov 23, 1994 11:17 AM
> According to Kernighan and Ritchie the \xnn syntax can have as many > hex digits as you like. Did these K & R guys do any _real_ programming, I wonder? Back in the days when they invented C, surely all characters were at most 8 bits long. Thanks for your help. Regards, Shraddhan (via AP from Hertfordshire, England)
#44219From: Steve GoddardNov 23, 1994 3:57 PM
Hi Shraddan, To answer your second Q: Define a struct: struct Lookup { char *string; int (*func)(void); /* Pointer to func taking no params and returning int */ }; Now you lookup table is an array of these, ie struct Lookup Table[]= { {"String 1", func1}, {"String 2", func2} }; Obviously, you must have some functions like int func1(void); Steve the G. [BEDFORDSHIRE, UK]
#44298From: ShraddhanNov 25, 1994 6:44 PM
Steve, Many thanks for your help. Regards, Shraddhan (via AP from Hertfordshire, England)
#44223From: Peter WadeNov 23, 1994 4:49 PM
> Did these K & R guys do any _real_ programming, I wonder? Well Ritchie invented Unix using C 🙂 > Back in the days when they invented C, surely all characters were at > most 8 bits long. Maybe not. I've heard that some of the minis and mainframes they used in those days had some weird word lengths. Before my time though. Peter Wade Autopiloting from London, England
#44254From: Marlene Zenker/SYSOPNov 24, 1994 4:17 PM
"weird word lengths" True. One of the CDC series (6400, maybe?) had a 60 bit word.
#44540From: Doug WalkerDec 3, 1994 9:11 AM
Well, I've read lots of answers to this question about the string constant, but there is one relatively easy solution that the ANSI committee suggests that works real well: #define WHATEVER "\x9b" "0 p" The ANSI standard says that adjacent string constants are concatenated by the tokenizer. Next best, but slightly less understandable, is the now-famous "\x9b\x30 p". –Doug
#44803From: ShraddhanDec 15, 1994 7:41 PM
Doug, Having asked the question that started this thread off, I went away and used the advice I had received. Some days later, I came back with an even more difficult problem (for me), but before I could compose my question, I found that you had already answered it. – Thanks! I had no idea that adjacent string constants would be concatenated by the tokenizer. I wonder why the authors of the books I looked at didn't seem to mention this – or at least, not bother to refer to the technique in the indexes to their books. Maybe I'm just too pedantic at heart, as I really like to be able to refer to books which give me the facts, the whole facts, and nothing but the facts. Unfortunately, such books seem nowadays to be few and far between – and out of print, too. Many years ago, I was dogmatically anti-'C'. A lot of my dislike of the language can be traced to the original K&R book, which has always struck me as being a half-baked attempt at defining a language. It seems to me that most 'C' books since then have followed their style. What I'm trying to say really is that I think I would have little hope of being able to write anything decent in C without the support I am able to receive here. Thanks again. Regards, Shraddhan (via AP from Hertfordshire, England)
#45063From: Doug WalkerJan 4, 1995 8:55 PM
Thanks – glad I could be of help. I don't know what books you are using, but string concatenation was an extension added by the ANSI committee and wasn't present in K&R. If you're using older books, it might not be mentioned (or maybe they were just too lazy to revise the example…) At the same time as string concatenation, the ANSI committee added "token pasting" and "stringization" operators to preprocessor macros. They work like this: #define FOO(x) abc##x #define STR(x) #x The macro invocation FOO(xyz) expands to abcxyz and the macro invocation STR(xyz) expands to "xyz". These are pretty useful in certain specific cases. –Doug