One liners for converting non-nullterminated arrays to string

H

helmuterik

I'd be interested in suggestions for one liners for converting two non-
nullterminated byte arrays such as "abc " and "def " (note that
both may or may not have a couple of trailing blanks) into a
nullterminated string where trailing blanks are removed, i.e. "abc/
def".

Thank you.
 
H

helmuterik

I'd be interested in suggestions for one liners for converting two non-
nullterminated byte arrays such as "abc   " and "def    " (note that
both may or may not have a couple of trailing blanks) into a
nullterminated string where trailing blanks are removed, i.e. "abc/
def".

Thank you.

The result should be "abc/def", no blank in there whatsoever. Sorry
for the typo.
 
S

Seebs

I'd be interested in suggestions for one liners

Why should this be a one liner?
for converting two non-
nullterminated byte arrays such as "abc " and "def " (note that
both may or may not have a couple of trailing blanks) into a
nullterminated string where trailing blanks are removed, i.e. "abc/
def".

Underspecified. Can the byte arrays contain internal spaces which are
not trailing spaces? If so, what do we do about those? Do you know the sizes
of these arrays?

-s
 
B

BartC

helmuterik said:
I'd be interested in suggestions for one liners for converting two non-
nullterminated byte arrays such as "abc " and "def " (note that
both may or may not have a couple of trailing blanks) into a
nullterminated string where trailing blanks are removed, i.e. "abc/
def".

The one-liner has to do the roughly the equivalent of joinstrings() in the
following code. Good luck with squeezing that into one line, especially if
it needs to worry about managing memory too.

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

int joinstrings(char* s, int slen, char* t, int tlen, char* dest){

while (slen && s[slen-1]==' ') --slen;
while (tlen && t[tlen-1]==' ') --tlen;

memcpy(dest,s,slen);
dest[slen]='/';
memcpy(dest+slen+1,t,tlen);
dest[slen+tlen+1]=0;

return slen+tlen+1;
}

int main(void){
char s[1000];

joinstrings("abc ",5,"def ",5,s);

printf("<%s>\n",s);
}
 
L

luser- -droog

I'd be interested in suggestions for one liners for converting two non-
nullterminated byte arrays such as "abc   " and "def    " (note that
both may or may not have a couple of trailing blanks) into a
nullterminated string where trailing blanks are removed, i.e. "abc/
def".

Thank you.

To make it a one-liner, remove all newlines.

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

int main() {
char a[3] = "abc";
size_t an = sizeof(a);
char b[3] = "def";
size_t bn = sizeof(b);

char *c;
c = malloc(an+1+bn+1);
memcpy(c,a,an);
c[an] = '/';
memcpy(c+1+an,b,bn);
c[an+1+bn] = '\0';
puts(c);
}
 
H

helmuterik

Why should this be a one liner?

I am just curious.
Underspecified.  Can the byte arrays contain internal spaces which are
not trailing spaces?  If so, what do we do about those?  Do you know the sizes
of these arrays?

True! No internal spaces allowed and they're both 10 bytes long, fixed
length. It's from a mainframe type environment.
 
B

BartC

Seebs said:
Underspecified. Can the byte arrays contain internal spaces which are
not trailing spaces?

I don't agree. The problem only mentions trailing blanks, suggesting that
leading or embedded blanks are ignored. (Although what 'blanks' are could do
with clarifying.)
If so, what do we do about those? Do you know the sizes
of these arrays?

If they are not nul-terminated, we have to assume that the sizes are known
by some other method.
 
B

Ben Bacarisse

helmuterik said:
I am just curious.


True! No internal spaces allowed and they're both 10 bytes long, fixed
length. It's from a mainframe type environment.

I was going to post the following as a solution, but a quick check
reveals that it's undefined (assume the byte arrays are in 'a' and 'b'):

int n;
sscanf(a, "%10[^ ]%n", res, &n);
res[n] = '/';
sscanf(b, "%10[^ ]", res + n + 1);

It's undefined because sscanf's first argument must be a string and your
non null-terminated arrays are not strings.

Apart from that (Mrs Lincoln) It would be a nice solution because sscanf
can limit the length of copying, stop on a space, and report the copied
length all in one call.
 
D

David Resnick

The result should be "abc/def", no blank in there whatsoever. Sorry
for the typo.

Not code I'd recommend for a variety of reasons. It does assume at
least one trailing blank, as I don't see how given the info provided
this can work (if it is not nul terminated and doesn't have any
blanks, how do you know where it ends?). Does all the actual work in
one awful line...

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

int main(void)
{
char abc[6] = "abc "; /* not nul terminated */
char def[6] = "def "; /* not nul terminated */
char *result = strncat(strncat( calloc(strcspn(abc, " ")
+strcspn(def, " ")+1,1), abc, strcspn(abc," ")), def, strcspn(def,"
"));

printf("%s\n", result);

free(result);

return 0;
}
 
D

David Resnick

Not code I'd recommend for a variety of reasons.  It does assume at
least one trailing blank, as I don't see how given the info provided
this can work (if it is not nul terminated and doesn't have any
blanks, how do you know where it ends?).  Does all the actual work in
one awful line...

AH, I see downthread max length of 10. Still one liner below if you
assume macro doesn't count, could substitute it manually if you REALLY
want to. Even more awful...

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

#define MAX 10
#define LEN(field) ( memchr((field),' ',MAX ) == NULL ? MAX :
( (char*)memchr((field),' ',MAX ) - (char*)(&(field)[0])) )

int main(void)
{

char abc[MAX] = "abc "; /* not nul terminated */
char def[MAX] = "def "; /* not nul terminated */

char *result = strncat(strncat( calloc(LEN(abc)+LEN(def)+1,1),
abc, LEN(abc)), def, LEN(def));

printf("%s\n", result);

free(result);

return 0;
}
 
D

David Resnick

AH, I see downthread max length of 10.  Still one liner below if you
assume macro doesn't count, could substitute it manually if you REALLY
want to.  Even more awful...

Reading more carefully, this sneaks in the "/" too. Mind you, anyone
putting this code into actual use should be shot, though if you
replace calloc with some "safe_calloc" variant that doesn't return on
failure it would actually work fine I believe.

char *result = strncat(strcat(strncat( calloc(LEN(abc)+LEN(def)
+2,1), abc, LEN(abc)), "/"), def, LEN(def));

-David
 
H

helmuterik

Reading more carefully, this sneaks in the "/" too.  Mind you, anyone
putting this code into actual use should be shot, though if you
replace calloc with some "safe_calloc" variant that doesn't return on
failure it would actually work fine I believe.

Thanks David! Now I can stick with a non-one-liner solution and feel
good about it.
 
K

Keith Thompson

helmuterik said:
I am just curious.

There are more interesting things to be curious about. There's no
benefit to doing this in one line of code.
True! No internal spaces allowed and they're both 10 bytes long, fixed
length. It's from a mainframe type environment.

What exactly does "No internal spaces allowed" mean? If there are
internal spaces, is that reported as an error (and if so, how)?
Or is the code just allowed to assume that there are no internal
spaces, and you don't care what happens if there are?
 
H

helmuterik

What exactly does "No internal spaces allowed" mean?  If there are
internal spaces, is that reported as an error (and if so, how)?
Or is the code just allowed to assume that there are no internal
spaces, and you don't care what happens if there are?

It means that in my particular environment the array holds the name of
an object whose name cannot contain spaces. That is, you can't create
objects violating this naming rule.
 
B

BartC

The one-liner has to do the roughly the equivalent of joinstrings() in the

BTW, if you want a real one-line answer, try a different language. Then it
might look like:

trim(a)+"/"+trim(b)

and not even take a whole line to itself. But if you want control over
exactly how it works, and or need to execute it billions of times, then be
prepared to invest a few extra lines when using C (lines don't cost much).
 
K

Keith Thompson

helmuterik said:
It means that in my particular environment the array holds the name of
an object whose name cannot contain spaces. That is, you can't create
objects violating this naming rule.

Which means that the code can safely assume that there are no
internal spaces, and you don't care what it does if it's given
a name that does contain internal spaces?

To be clear, I'm not saying that you *should* care, just that if
you don't you should clearly document that fact.
 
K

Keith Thompson

Seebs said:
I guess, I have no interest in trying to make things into one-liners
these days. You probably could, but it seems pointless.

One-liners can be quite useful for interpretive languages where
you can interactively type something in a shell command line (or
whatever your system's equivalent is). Awk and Perl are both good
for this kind of thing.

For compiled languages like C, where programs are in text files,
there's no particular advantage in one-liners (unless you're trying
to show off how terse you can be).
 
K

Kenny McCormack

Keith Thompson said:
For compiled languages like C, where programs are in text files,
there's no particular advantage in one-liners (unless you're trying
to show off how terse you can be).

Suppose a pretty girl offers to have sex with you if you can do it in
one line?

Suppose a rich man offers you a dream job if you can do it in
one line?

Somehow, I doubt either one of these (certainly not the first) would
sway either Seebs or Kiki...

--
Is God willing to prevent evil, but not able? Then he is not omnipotent.
Is he able, but not willing? Then he is malevolent.
Is he both able and willing? Then whence cometh evil?
Is he neither able nor willing? Then why call him God?
~ Epicurus
 
L

luser- -droog

Suppose a pretty girl offers to have sex with you if you can do it in
one line?

Suppose a rich man offers you a dream job if you can do it in
one line?

Somehow, I doubt either one of these (certainly not the first) would
sway either Seebs or Kiki...

Dude, why are you always such a dick?
 

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,769
Messages
2,569,581
Members
45,056
Latest member
GlycogenSupporthealth

Latest Threads

Top