Solved

Simple C Question - Splitting a string

Posted on 2004-04-28
20
828 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
  • 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
 
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
Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

 
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 100 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

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

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…
Windows programmers of the C/C++ variety, how many of you realise that since Window 9x Microsoft has been lying to you about what constitutes Unicode (http://en.wikipedia.org/wiki/Unicode)? They will have you believe that Unicode requires you to use…
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use for-loops in the C programming language.
The goal of this video is to provide viewers with basic examples to understand and use conditional statements in the C programming language.

708 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

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now