?
Solved

Simple C Question - Splitting a string

Posted on 2004-04-28
20
Medium Priority
?
839 Views
Last Modified: 2010-04-02
Hey What is the best way to
take a string and make a new string from its first two characters ?
Thanks Foggy
0
Comment
Question by:paddyOBrien
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 9
  • 5
  • 3
  • +2
20 Comments
 
LVL 46

Expert Comment

by:Sjef Bosman
ID: 10941023
The fastest:

char *s= "abcdef";
char news[3];

news[0]= *s++;
news[1]= *s;
news[2]= '\0';

What's your code, 'coz this isn't probably what you want...
0
 
LVL 46

Expert Comment

by:Sjef Bosman
ID: 10941055
There's also strncpy, where you can set how long a string is to be. See your manual
0
 
LVL 10

Expert Comment

by:Mercantilum
ID: 10941061
Yes, sjef, you were the fastest :)
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
LVL 4

Expert Comment

by:PerryDK
ID: 10942048
Since your in the C group I will assume you don't have access to std::string which is availble in C++ and you have to be using char* as your strings.

char* oldStr = "hello";

#define MAX_SUB_STRING_LENGTH 10
char subStr[10];

void getSubString(char* source, char* dest, int index, int count)
{
  memcpy(dest, &source[index], count);
  dest[count] = '\0';
}


now to get your first two characters just do this

getSubString(oldStr, subStr, 0, 2);

subStr will now contain a string with just the first two characters of oldStr
0
 
LVL 10

Expert Comment

by:Mercantilum
ID: 10942158
Well, in this case, you could do this which creates dynamically a string

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

// return pointer to an allocated string of length chars (length+1 for trailing 0)

char *make_new_string (char *source, int length)
{
    char *alloc;

    alloc = malloc (length+1);
    strncpy (alloc, source, 2);
    alloc[2] = 0;
    return (alloc);
}

// main

int main ()
{
   char *firststring = "cool bool";
   char *second;

    second = make_new_string (firststring, 50);

     printf ("%s  %s\n", firststring, second);
}

Somebody gets an idea for a recursive func ??
0
 
LVL 4

Expert Comment

by:PerryDK
ID: 10942356
Mercantilum,

In gerneral I would steer clear of returning allocated memory from a function.  Its best to have the user allocate his own memory and pass it into the function.  The problem with having a function returning allocated memory is that the user then becomes responsible for knowing the implementation details of the function and know that for this function they are explicitly responsible for deallocting the memory that was returned from the function.

If you force the user to allocate his own memory and then pass it into the function...the user is aware that he allocated the memory and is thus already aware that he is responsible for deallocating it.

Case In point...your main function has a memory leak :)
You did not deallocate the memory that the variable second is pointing too.
0
 
LVL 10

Expert Comment

by:Mercantilum
ID: 10944978
In this case the user creates the function and uses it himself :)
0
 
LVL 4

Expert Comment

by:PerryDK
ID: 10945189
Even if you are the end user I would still stay clear of returning allocated memory in a function.  You the user created the function so you know of the implemention details.  Even with that knowledge you still forgot to deallocate before your main function ended.  Once your program gets big enough it will be impossible to keep every little detail in your head.  Even if you are the end user of the function, returning allocated memory from a function still creates a little detail that you have to be aware of.  Its just good programming practice to minimise the number of things that you have to keep track of all the time.
0
 
LVL 10

Expert Comment

by:Mercantilum
ID: 10945332
He Perry all here agree that it is better not to let the caller free the mem alloc by the func :)
we are trying to find a way to answer the question - this is one of them... come on...
0
 
LVL 4

Expert Comment

by:PerryDK
ID: 10945374
Sorry wasn't trying to offend you was just trying to point out the potential for errors with that particular solution.

The author already has 3 viable solutions...he must have forgot about his question :)
0
 
LVL 10

Expert Comment

by:Mercantilum
ID: 10945395
Ok, by the way

1.  I don't think it is good practice to teach a program to a beginner without indicating the include, like #include <string.h> for memcpy.
Can be dangerous if the compiler doesn't warn.

2.  To copy a substring better to use strncpy - name fits better than memcpy. Especially in your case where you copy n bytes, even if the source could be much less than n bytes :)

3.  These copy functions are usually (dest, source) and not the opposite - not a good practice to do the opposite of the libs

4.  The char *oldStr should have been declared as static.

5.  I don't think it is the best practice to use global vars.

no offense :)
0
 
LVL 4

Expert Comment

by:PerryDK
ID: 10945427
you have valid points and I agree with all of them.  
0
 
LVL 10

Expert Comment

by:Mercantilum
ID: 10945499
I know it is usually not considered as a good practice to use recursive funcs  :)

#include <stdio.h>

// copyn copies n chars, 1 char at a time and set the trailing (char)0 :)

static void copyn (char *dest, const char *source, int n)
{
  if (n <= 0) *dest = (char)0;
  else
  {
    *dest = *source;
    copyn (dest+1, source+1, n-1);
  }
}

// example of main ()

int main ()
{
  const char *from = "what about that";
  char to[10];

  copyn (to, from, 2);

  printf ("'%s' '%s'\n", from, to);

  return (0);
}
0
 
LVL 10

Expert Comment

by:Mercantilum
ID: 10945524
AND there is no control of size limit, e.g. if 'dest' is not big enough, copy will go beyond its limits (length of 9 in this case :)
(ouf!)
0
 
LVL 4

Expert Comment

by:skypalae
ID: 10946264
Hi guys,
fine discussion here. I don't understand the words "best way"? Is it "fastest" or "shortest" or "most compatible"?

the fastest (and shortest i think) would be:
    char s1[] = "abcd" ; // directly on the stack
    char *s2 = s1 ; // indirect

    char d1[3] ; // directly on the stack
    char *d2 = d1 ; // indirect

    // if you need allways and only the 2byte string, you can keep the 3rd byte allways '\0'
    // so if you're getting the 2byte string in a loop you can ceep the following outside the loop
    d1[3] = '\0' ;

    // typing the arrays to word size compiles the assignment into 2-4 assembler instructions (depending on strings declaration)
    ((short*)d1)[0] = ((short*)s1)[0] ;
    // mov         dx,word ptr [ebp-8]
    // mov         word ptr [ebp-10h],dx
    ((short*)d1)[0] = ((short*)s2)[0] ;
    // mov         eax,dword ptr [ebp-0Ch]
    // mov         cx,word ptr [eax]
    // mov         word ptr [ebp-10h],cx
    ((short*)d2)[0] = ((short*)s1)[0] ;
    // mov         edx,dword ptr [ebp-14h]
    // mov         ax,word ptr [ebp-8]
    // mov         word ptr [edx],ax
    ((short*)d2)[0] = ((short*)s2)[0] ;
    // mov         ecx,dword ptr [ebp-14h]
    // mov         edx,dword ptr [ebp-0Ch]
    // mov         ax,word ptr [edx]
    // mov         word ptr [ecx],ax

but creating the 2char string from bigger string is fast enough that you needn't to count the assembler instructions (especially on machines like PPro 2GHz :))

the most compatible would be (as you pointed) use strncpy() function

Cheers! S.
0
 

Author Comment

by:paddyOBrien
ID: 10946970
Hi I actually have access to std:string as it is in C++. How would that make it easier ?
0
 
LVL 10

Expert Comment

by:Mercantilum
ID: 10946986
string first = "abracadabra";
string second = first.substr (0, 2);
0
 
LVL 10

Accepted Solution

by:
Mercantilum earned 400 total points
ID: 10947021
If you want to try at home :)

#include <iostream>
#include <string>

using namespace std;

// copy 2 first chars of first into second
// then print the 2 values

int main()
{
    string first = "abracadabra";
    string second = first.substr (0, 2);
    cout << first     << endl;
    cout << second << endl;
}
0
 

Author Comment

by:paddyOBrien
ID: 10947139
Thanks for all the help people
Much appreciated
Points to Mercantilum
Thank you :-)
0
 
LVL 46

Expert Comment

by:Sjef Bosman
ID: 10947268
So it was a simple C++ question! Wrong TA...

Sjef :(
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This tutorial is posted by Aaron Wojnowski, administrator at SDKExpert.net.  To view more iPhone tutorials, visit www.sdkexpert.net. This is a very simple tutorial on finding the user's current location easily. In this tutorial, you will learn ho…
This is a short and sweet, but (hopefully) to the point article. There seems to be some fundamental misunderstanding about the function prototype for the "main" function in C and C++, more specifically what type this function should return. I see so…
The goal of this video is to provide viewers with basic examples to understand and use structures in the C programming language.
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use nested-loops in the C programming language.
Suggested Courses

764 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question