simple way to get rid of leading zeors in a string in C - Page 1
Forum section: electronics / general

author: kgavionics
author_rank: Regular Contributor
timestamp: April 22, 2023, 03:10:03 pm
content: Hello everyoneI have a function that convert a long to a string (array of 8 chars), but my problem is that outputs all the leading zeros, I want to get rid of all of them in a simple way, I don't use any Sprintf or printf of any kind.I started by counting all 0 a string, but I'm stuck on how to remove them!Code:int main(){char s="00001111"; // just an example of a stingchar j;for(char i=0;i<7;i++){if (s !='0')break;elsej++;// j is the number of zeos in the string}//I'm stuck here}}Can someone gives me some help how to achieve this in a simple way please!TIA

author: mitb67
author_rank: Newbie
timestamp: April 22, 2023, 03:34:10 pm
content: Hi.Use strspn function.Code:// C Program to Remove leading zeros// using strspn#include <stdio.h>#include <string.h>int main(){/*** input string*/char* s = "0001234";int n;/*** strspn->Returns the length of the first segment of str1 that exclusively contains characters from str2.*/if ((n = strspn(s, "0")) != 0 && s != '\0') {// printing the string after eliminating the zerosprintf("%s", &s);}return 0;}

author: KrudyZ
author_rank: Frequent Contributor
timestamp: April 22, 2023, 03:41:25 pm
content: char * stripstr(char * string) {while(*string == '0')string++;return (string);}edited to correct pointer dereference...code assumes standard NULL terminated C strings...

author: grumpydoc
author_rank: Super Contributor
timestamp: April 22, 2023, 03:42:10 pm
content: When you say "get rid of them", what do you mean exactly?Your initialisation of "s" in the example suggests you are not working with C nul terminated strings and want to work with fixed length strings, could you clarify this point?Quote from: mitb67 on April 22, 2023, 03:34:10 pmI get the impression we're trying to avoid standard libraries - it might be good if kgavionics could let us know if that is the case or it's just printf he wants to avoid (to be fair *printf can get pretty big in terms of code generation).

author: grumpydoc
author_rank: Super Contributor
timestamp: April 22, 2023, 03:46:32 pm
content: Quote from: KrudyZ on April 22, 2023, 03:41:25 pm&string is the address of a variable so &string == '0' is not going to be much use.Even if you write it more correctly as *string == '0' what does your function do if there are already no leading zeros?Ah, I see you reallised it should be *, not & - my question still stands though

author: AVI-crak
author_rank: Regular Contributor
timestamp: April 22, 2023, 03:49:03 pm
content: Strange move: write zeros, delete zeros. The string is obtained from a number that at some point becomes zero, at which point you need to stop and return the pointer.

author: KrudyZ
author_rank: Frequent Contributor
timestamp: April 22, 2023, 03:49:22 pm
content: Quote from: grumpydoc on April 22, 2023, 03:46:32 pmIf there are no leading '0' the while will immediately fall trough and the original string is returned.

author: grumpydoc
author_rank: Super Contributor
timestamp: April 22, 2023, 03:57:13 pm
content: Quote from: AVI-crak on April 22, 2023, 03:49:03 pmAgree, I was going to make the point that if the OP is rolling his own long->string function not generating the leading zeros would be much better.However I don't think we've cleared up the point about how the strings are to be represented in memory - whether as standard C nul terminated strings, or as fixed length buffers.Code:char s="00001111";Has a character array of length 8, correctly initialised, without a terminating '\0'.Code:char s="00001111";Would have been correct for a standard C striing.

author: grumpydoc
author_rank: Super Contributor
timestamp: April 22, 2023, 04:02:11 pm
content: Quote from: KrudyZ on April 22, 2023, 03:49:22 pmSorry, should have said what's the output if the input is "00000000", or "0" for that matter?

author: dobsonr741
author_rank: Frequent Contributor
timestamp: April 22, 2023, 04:12:10 pm
content: QuotePlease show us the function and how you call call it when coverting the long to a string. Your example code is not doing that.

author: RoGeorge
author_rank: Super Contributor
timestamp: April 22, 2023, 04:35:06 pm
content: Code:#include <stdio.h>int main() {// char s="00001111"; //you sure you want 8 and not 9?char s[]="00001111"; //better let the compiler countchar *p;for(p=s; *p=='0' && *p; p++); //that's allprintf("P now points to what's left:\n");printf("%s\n", p);return 0;}P now points to what's left:1111

author: Sacodepatatas
author_rank: Regular Contributor
timestamp: April 22, 2023, 05:21:31 pm
content: In what format should be the number in the output string? Decimal? Hex? (I suppose hex because you only use a 8 char buffer, but, whatever).

author: AVI-crak
author_rank: Regular Contributor
timestamp: April 22, 2023, 05:29:34 pm
content: Quote from: grumpydoc on April 22, 2023, 03:57:13 pmI agree, it remains to convince thekgavionics. But I don't think he cares anymore.Code example without leading zeros.https://github.com/AVI-crak/Rtos_cortex/blob/c82689fd4fadfaa3113e97ddf923e670acae7e11/sPrint.c#L120

author: kgavionics
author_rank: Regular Contributor
timestamp: April 22, 2023, 07:24:09 pm
content: Sorry guys for my late reply, I was away from home!I want to stay away from printf, because it is not suited for small microcontroller due to its size!@dobsonr741 : the function that I use to convert the long to string, is the following:Code:void UlToStr(char* s, unsigned long bin, unsigned char n){s += n;*s = '\0';while (n--){*--s = (bin % 10) + '0';bin /= 10;}}

author: kgavionics
author_rank: Regular Contributor
timestamp: April 22, 2023, 08:16:25 pm
content: Quote from: RoGeorge on April 22, 2023, 04:35:06 pmCan you please tell me how to put your modification, in my function above please?

author: SiliconWizard
author_rank: Super Contributor
timestamp: April 22, 2023, 08:17:34 pm
content: Quote from: kgavionics on April 22, 2023, 07:24:09 pmJust exit the loop when bin becomes zero, and return the current value of s from the function, which you will use as the pointer to the string later on.

author: kgavionics
author_rank: Regular Contributor
timestamp: April 22, 2023, 08:33:27 pm
content: I tried to modify my function to return a pointer, but I get this error:conversion.c(25): error: conflicting types for 'UlToStr'Code:char * UlToStr(char* s, unsigned long bin, unsigned char n){s += n;*s = '\0';while (n--){*--s = (bin % 10) + '0';bin /= 10;}char *p;for(p=s; *p=='0' && *p; p++);return p;}

author: AVI-crak
author_rank: Regular Contributor
timestamp: April 22, 2023, 08:44:58 pm
content: Quote from: kgavionics on April 22, 2023, 07:24:09 pmdestination - printo() macro - faster printf 6 times,printo("text", double, float, uint(8-16-32-64)_t, int(8-16-32-64)_t ),returns a classic string with a terminal null - convenient for dma,printing without specifying the variable type, up to 9 variables and constants at the same time,has no external dependencies, all functions are thread independent,minimum weight +140 bytes, full set 1684 bytes, maximum speed 20~470 ticks,does not use in calculations: division and floating point, optimized for ARMIs this size okay?

author: kgavionics
author_rank: Regular Contributor
timestamp: April 22, 2023, 08:47:43 pm
content: Quote from: AVI-crak on April 22, 2023, 08:44:58 pmYes, this is perfect for me! link please!

author: RoGeorge
author_rank: Super Contributor
timestamp: April 22, 2023, 08:55:41 pm
content: Try this:Code:void UlToStr(char* s, unsigned long bin, unsigned char n) {s += n;*s = '\0';do {*--s = (bin % 10) + '0';bin /= 10;}while (--n && bin);}

author: kgavionics
author_rank: Regular Contributor
timestamp: April 22, 2023, 09:05:42 pm
content: Quote from: RoGeorge on April 22, 2023, 08:55:41 pmdoesn't work at all I get "o" as fixed output, instead of 00000000.

author: AVI-crak
author_rank: Regular Contributor
timestamp: April 22, 2023, 09:09:25 pm
content: Quote from: kgavionics on April 22, 2023, 08:47:43 pmhttps://github.com/AVI-crak/Rtos_cortex/blob/master/sPrint.crewrite the receiver for your system - there is a line with a terminal zero.static inline void soft_print(char* txt){ M_print_OS(txt);};It works equally fast everywhere, I even checked it on WCH chips. For M0, the speed drops, but not 30 times as for printf.But you have to forego the printf() formatting commands, my printo() macro recognizes the type of the variable automatically.

author: RoGeorge
author_rank: Super Contributor
timestamp: April 22, 2023, 09:25:56 pm
content: Quote from: kgavionics on April 22, 2023, 09:05:42 pmYou get letter 'o'?When all is 00000000 it displays one 0.You wrote you want to get rid of the extra zeroes, so it only return one zero instead of 7 extra zeroes and one useful zero to display. Now you want to have all eight zeroes 00000000?You have to explain properly what you wish. I give up. Good luck with it.

author: kgavionics
author_rank: Regular Contributor
timestamp: April 22, 2023, 09:44:38 pm
content: Quote from: RoGeorge on April 22, 2023, 09:25:56 pmYour first code worked without my function, but the second (the modified function with your code) doesn't output anything, I tested it both on keil arm uvision and my computer using codeblocks!https://youtu.be/ku0C5ZqYrUY

author: kgavionics
author_rank: Regular Contributor
timestamp: April 22, 2023, 10:20:06 pm
content: Quote from: AVI-crak on April 22, 2023, 09:09:25 pmI added the files sPrint.c and monitor.c to my project and I compiled without using any function, just to see how it works, but it generated so many errors (see attached text files)! I hope I'm not doing someone thing stupid here!

author: cv007
author_rank: Frequent Contributor
timestamp: April 22, 2023, 10:21:56 pm
content: QuoteWhich mcu is in use? Which compiler?

author: DavidAlfa
author_rank: Super Contributor
timestamp: April 22, 2023, 10:40:51 pm
content: If you only want to generate a string, try itoa() or ftoa(), much lighter than(s)printf, but you can't configure the output in any way.Doesn't print leading zeros, though.

author: kgavionics
author_rank: Regular Contributor
timestamp: April 22, 2023, 10:43:47 pm
content: Quote from: cv007 on April 22, 2023, 10:21:56 pmCurrently, I use a stm32f401 under keil arm uvison ( gcc), but I'm using avr 328p for other projects under Atmel studio ( gcc as well)!

author: kgavionics
author_rank: Regular Contributor
timestamp: April 22, 2023, 11:04:30 pm
content: Quote from: DavidAlfa on April 22, 2023, 10:40:51 pmI looked for these function under stdlib (arm gcc), but they are not there! Where can I find them?

author: AVI-crak
author_rank: Regular Contributor
timestamp: April 22, 2023, 11:08:45 pm
content: I'm using gcc-arm-none-eabi-10_3, and RISC-V Embedded GCC - I don't get these errors.Keil_v5 practices stricter code rules that are partly incompatible with GCC.Rewriting code for Keil will require a separate project, and time. But I don't use Keil.monitor.c is shared with the embitz1.1 IDE, I doubt you have it.I explicitly indicated to write my own version of the soft_print(char* txt) function, because this is an output to a physical communication channel.Here is a part of my code, it works without warnings, although a little meaningless GCC.https://rextester.com/ODE66849

author: cv007
author_rank: Frequent Contributor
timestamp: April 22, 2023, 11:32:47 pm
content: QuoteNeither case is an mcu to avoid printf/snprintf.The avr printf is lightweight and easy to use. The arm takes some work to hook up printf to a destination, but snprintf is easy to use and is used the same for any mcu or pc, and your particular arm could fit printf on its little pinky fingernail. You can be 'bare metal' and still know when its better to use something that already exists.avr printf (no great need to avoid printf in favor of snprintf as hooking up printf to a function is easy)-https://godbolt.org/z/dGxG5a6Gh(printf library increases code size by about 1.5k)pc printf can be used to test-https://godbolt.org/z/5qz7T6MeeWith the standard printf/snprintf you will have documentation, the ability to use/test on any mcu or pc, can get rid of all the little custom formatting functions you may be trying to use now, and once you start to use it you will wonder why you were trying to replace it.An snprintf type for the arm where the buffer is on the stack, formatted, sent away to a function (which could put it in its own buffer, or direct to hardware), and returns when done (buffer on stack gets destroyed on return, but is ok since already transferred/used)-https://godbolt.org/z/q7K3n5Mzzshould be vsnprintf, not snprintfhttps://godbolt.org/z/e1casGbbn(vsnprintf adds about 3k in code size)Lots of variations to get the same results, but the common denominator is you are dealing with the same printf style format description syntax.

author: AVI-crak
author_rank: Regular Contributor
timestamp: April 23, 2023, 11:46:42 am
content: Quote from: kgavionics on April 22, 2023, 10:20:06 pmI cleaned the functions from GCC features, now the code should build in Keil without errors.As before, you first need to create a bufferCode:char print_buf12;, and pass a pointer to the last element to the function.Code:&print_buf12This method allows you to avoid errors - you can immediately see the size of the buffer.Code:char* u32_char_m3 (char* tail_txt, uint32_t value){uint32_t res, tmp, drr;drr = 3435973837UL;*tail_txt = 0;do{tmp = (uint32_t)((uint64_t) value * drr >> 32);res = value + '0';value = tmp >> 3;tmp = value + (value << 2);res -= tmp << 1;*(--tail_txt) = res;}while (value);return tail_txt;};char * i32_char_m3(char* tail_txt, int32_t value){int32_t mi = value >> 31;if (mi) value = 0 - value;tail_txt = u32_char_m3(tail_txt, (uint32_t)value);*(tail_txt - 1) = '-';tail_txt += mi;return tail_txt;};The functions are already optimized for high speed, and small size. Despite the large number of symbols, the assembler code is compact and fast. Slow commands (divide and take a percentage) are not involved.However, I strongly advise you to abandon Keil in favor of a more modern IDE.

author: kgavionics
author_rank: Regular Contributor
timestamp: April 23, 2023, 02:13:30 pm
content: Quote from: AVI-crak on April 23, 2023, 11:46:42 amDo you have any suggestion please?

author: AVI-crak
author_rank: Regular Contributor
timestamp: April 23, 2023, 04:41:44 pm
content: You have no restrictions, unlike me (Russia).I prefer to use frozen IDEs that don't update on their own with the complete destruction of all projects: embitz1.1, MounRiver Studio, Code::Blocks, as well as a large list of fast online services.I highly recommend installing TortoiseGit (for home), and Git for the outside world. It's very hard to write anything serious without version control. You will be haunted by mistakes that cannot be corrected.The list of IDEs available to you - can be found through search engines in a couple of minutes.

author: kgavionics
author_rank: Regular Contributor
timestamp: April 23, 2023, 04:45:45 pm
content: Quote from: AVI-crak on April 23, 2023, 04:41:44 pmThank you for the heads-up AVI-crak!

author: dobsonr741
author_rank: Frequent Contributor
timestamp: April 23, 2023, 11:37:31 pm
content: QuoteI was in this camp, until I realized it’s not sustainable. So I switched to Cmake + vs Code.This way the build is not dependent on the IDE, and the build can run from the command line any time. Or from CI, if I really want to be fancy.I agree, git is a must.