Printing String from a char array? - arrays

Currently the code should replace all spaces in a string with %20. For the most part, I think the logic is right on the method I make a call to, but when I want to see the returned result I my main method prints nothing -- it prints a blank for the string. Could someone direct me where my my logic in turning the array into a string is incorrect? Thanks for the time and help. I attached my code for the method in case you guys needed it. Sorry if the mistake is dumb.
public class replaceSpaces {
public static void main(String[] args) {
char[] data = checkfor20("yo o");
String text = String.valueOf(data); //turn char array into string representation
System.out.println(" new one: " + text);
}
private static char[] checkfor20(String string) {
int check = string.length(); //length of string
int spaceCount = 0, newLength; //count spaces and new length with %20 put in
char[] charstring = string.toCharArray(); // turn string into char array
for(int i = 0; i < check ; i++) { //get space count for newlenght
if (charstring[i] == ' ') {
spaceCount++;
}
}
newLength = check + (spaceCount * 2);
char[] newArray = new char[newLength];
for(int i = check - 1; i >= 0; i--) {
if(newArray[i] == ' ') { //get spaces and put it
newArray[newLength - 1 ] = '0';
newArray[newLength - 2 ] = '2';
newArray[newLength - 3 ] = '%';
newLength = newLength - 3;
}
else {
newArray[newLength - 1] = charstring[i];
newLength = newLength - 1;
}
}
return newArray; //return the new char array
}}

Why not newstring = oldstring.replace(" ","%20");?

Apologizes for the mistake on my part I was supposed to just change my array into
if(charstring[i] == ' ')
rather than the new array I created.

Related

Inserting %20 in a string character clarification

Hi I am doing a Cracking the Coding I have coded up a solution, by reading the answer explained in plain english, however I do not understand one line of code.
The Question
Replace all white space with "%20", empty spaces have been added at the end of the text to accomodate for the new symbols
Input : "Mr John Smith ", 13
Output : Mr%20John%20Smith
My Solution
*static void replaceSpaces(char[] arr,int trueLength)
{
int spaces = 0;
int newLength = 0;
int length = 0;
for(int i = 0; i<trueLength; ++i)
{
if(arr[i] == ' ')
{
++spaces;
}
newLength = trueLength +spaces*2; // We already have one space, so we need to add 2 extra spaces to fit the %20 symbol
}
for(int i = trueLength-1; i>=0; i--)
{
if(arr[i] == ' ')
{
arr[newLength-1] = '0';
arr[newLength-2] = '2';
arr[newLength-3] = '%';
newLength = newLength - 3;
}
else
{
arr[newLength-1] = arr[i];
newLength = newLength - 1;
}
}
System.out.println(arr);
}*
I dont understand why we need this line of code (newLength = newLength - 3), I think we need it because after we remove space with the symbol, we subtract 3 to go to the next empty space, is this correct?
That's correct, if you mean: to the next empty space to write a new character.
The codeline newLength = newLength - 3; exists because you need to skip 3 characters ('0', '2' and '%'). Else you would overwrite them.
I must mention that your code is quite typical since you are filling the array backwards.

How do I convert an underscored pointer to a char array into camelCasing?

I am trying to write a function that will convert a "word_string" to "wordString". However, my output from the code below is "wordSttring". I'm having trouble skipping to the next element of the array after I replace the undescore with the uppercase of the next element. Any suggestions?
void convert_to_camel(char* phrase){
int j =0;
for(int i=0;i<full_len-1;i++){
if(isalphanum(phrase[i])){
phrase[j] = phrase[i];
j++;
length++;
}
}
int flag = 0;
char new[50];
for (int i=0;i<length;i++){
if(phrase[i]== '95'){
flag = 1;
}
if(flag ==1){
new[i] = toUpper(phrase[i+1]);
i++;
new[i] = phrase[i+1];
flag = 0;
}
else{
new[i] = phrase[i];
}
}
All other solutions presented so far turn "_" into an empty string and remove _ from the end of the string.
#include <stddef.h>
#include <ctype.h>
void to_camel_case(char *str) // pun_intended
{
for (size_t i = 0, k = 0; str[i]; ++i, ++k)
{
while (k && str[k] == '_' && str[k + 1]) // 1)
str[k] = k - 1 ? toupper((char unsigned)str[++k]) : str[++k]; // 2)
str[i] = str[k];
}
}
Skip consecutive '_'. Make sure to leave at least one at the beginning and one at the end of the string if present.
Replace '_' with the next character, capitalized if needed.
You are not handling the removing _ properly for that you need one more loop index(j).
And you don't need one more loop to remove the non alpha numeric chars it can be done with _ loop only,
also you need to terminate the string once trimming is completed otherwise your string will have junk chars.
void toCamelCase(char* phrase){
int j=0;
for (int i=0;i<strlen(phrase);i++){
if(phrase[i] != '_' && isalnum(phrase[i])){ //Copy Alpha numeric chars not including _.
phrase[j++] = phrase[i];
}
else if(phrase[i] == '_'){
phrase[j++] = toupper(phrase[i+1]);
i++;
}
}
phrase[j] = '\0'; //Terminate the string
}
Note::This method does not handle consecutive _(word____string).
Note that in your current implementation you are trying to use new character array to store the processed string but you won't be able to use it outside that function since it is local variable and its end of life is the very moment the flow exits that function.
Here is my proposal for such function:
#define MAX_STR_LEN 50
// assuming that 'str' is a null terminated string
void to_camel_case(char *str)
{
int idx = 0;
int newIdx = 0;
int wasUnderscore = 0;
// just to be on the safe side
if (!str || strlen(str) >= MAX_STR_LEN)
return;
while (str[idx])
{
if (str[idx] == '_')
{
idx++;
// no copy in this case, just raise a flag that '_' was met
wasUnderscore = 1;
}
else if (wasUnderscore)
{
// next letter after the '_' should be uppercased
str[newIdx++] = toupper(str[idx++]);
// drop the flag which indicates that '_' was met
wasUnderscore = 0;
}
else
{
// copy the character and increment the indices
str[newIdx++] = str[idx++];
}
}
str[newIdx] = '\0';
}
I tested it with some inputs and this is what I got:
String hello_world became helloWorld
String hello___world became helloWorld
String hel_lo_wo_rld__ became helLoWoRld
String __hello_world__ became HelloWorld
Maybe something like this might help :
void toCamelCase(char* phrase){
int length = strlen(phrase);
int res_ind = 0;
for (int i = 0; i < length ; i++) {
// check for underscore in the sentence
if (phrase[i] == '_') {
// conversion into upper case
phrase[i + 1] = toupper(s[i + 1]);
continue;
}
// If not space, copy character
else
phrase[res_ind++] = s[i];
}
phrase[res_ind] = '\0';
}

code accounting for multiple delimiters isn't working

I have a program I wrote to take a string of words and, based on the delimiter that appears, separate each word and add it to an array.
I've adjusted it to account for either a ' ' , '.' or '.'. Now the goal is to adjust for multiple delimiters appearing together (as in "the dog,,,was walking") and still only add the word. While my program works, and it doesn't print out extra delimiters, every time it encounters additional delimiters, it includes a space in the output instead of ignoring them.
int main(int argc, const char * argv[]) {
char *givenString = "USA,Canada,Mexico,Bermuda,Grenada,Belize";
int stringCharCount;
//get length of string to allocate enough memory for array
for (int i = 0; i < 1000; i++) {
if (givenString[i] == '\0') {
break;
}
else {
stringCharCount++;
}
}
// counting # of commas in the original string
int commaCount = 1;
for (int i = 0; i < stringCharCount; i++) {
if (givenString[i] == ',' || givenString[i] == '.' || givenString[i] == ' ') {
commaCount++;
}
}
//declare blank Array that is the length of commas (which is the number of elements in the original string)
//char *finalArray[commaCount];
int z = 0;
char *finalArray[commaCount] ;
char *wordFiller = malloc(stringCharCount);
int j = 0;
char current = ' ';
for (int i = 0; i <= stringCharCount; i++) {
if (((givenString[i] == ',' || givenString[i] == '\0' || givenString[i] == ',' || givenString[i] == ' ') && (current != (' ' | '.' | ',')))) {
finalArray[z] = wordFiller;
wordFiller = malloc(stringCharCount);
j=0;
z++;
current = givenString[i];
}
else {
wordFiller[j++] = givenString[i];
}
}
for (int i = 0; i < commaCount; i++) {
printf("%s\n", finalArray[i]);
}
return 0;
}
This program took me hours and hours to get together (with help from more experienced developers) and I can't help but get frustrated. I'm using the debugger to my best ability but definitely need more experience with it.
/////////
I went back to pad and paper and kind of rewrote my code. Now I'm trying to store delimiters in an array and compare the elements of that array to the current string value. If they are equal, then we have come across a new word and we add it to the final string array. I'm struggling to figure out the placement and content of the "for" loop that I would use for this.
char * original = "USA,Canada,Mexico,Bermuda,Grenada,Belize";
//creating two intialized variables to count the number of characters and elements to add to the array (so we can allocate enough mmemory)
int stringCharCount = 0;
//by setting elementCount to 1, we can account for the last word that comes after the last comma
int elementCount = 1;
//calculate value of stringCharCount and elementCount to allocate enough memory for temporary word storage and for final array
for (int i = 0; i < 1000; i++) {
if (original[i] == '\0') {
break;
}
else {
stringCharCount++;
if (original[i] == ',') {
elementCount++;
}
}
}
//account for the final element
elementCount = elementCount;
char *tempWord = malloc(stringCharCount);
char *finalArray[elementCount];
int a = 0;
int b = 0;
//int c = 0;
//char *delimiters[4] = {".", ",", " ", "\0"};
for (int i = 0; i <= stringCharCount; i++) {
if (original[i] == ',' || original[i] == '\0') {
finalArray[a] = tempWord;
tempWord = malloc(stringCharCount);
tempWord[b] = '\0';
b = 0;
a++;
}
else {
tempWord[b++] = original[i];
}
}
for (int i = 0; i < elementCount; i++) {
printf("%s\n", finalArray[i]);
}
return 0;
}
Many issues. Suggest dividing code into small pieces and debug those first.
--
Un-initialize data.
// int stringCharCount;
int stringCharCount = 0;
...
stringCharCount++;
Or
int stringCharCount = strlen(givenString);
Other problems too: finalArray[] is never assigned a terminarting null character yet printf("%s\n", finalArray[i]); used.
Unclear use of char *
char *wordFiller = malloc(stringCharCount);
wordFiller = malloc(stringCharCount);
There are more bugs than lines in your code.
I'd suggest you start with something much simpler.
Work through a basic programming book with excercises.
Edit
Or, if this is about learning to program, try another, simpler programming language:
In C# your task looks rather simple:
string givenString = "USA,Canada Mexico,Bermuda.Grenada,Belize";
string [] words = string.Split(new char[] {' ', ',', '.'});
foreach(word in words)
Console.WriteLine(word);
As you see, there are much issues to worry about:
No memory management (alloc/free) this is handeled by the Garbage Collector
no pointers, so nothing can go wrong with them
powerful builtin string capabilities like Split()
foreach makes loops much simpler

Split String into String array

I have been playing around with programming for arduino but today i've come across a problem that i can't solve with my very limited C knowledge.
Here's how it goes.
I'm creating a pc application that sends serial input to the arduino (deviceID, command, commandparameters). This arduino will transmit that command over RF to other arduino's. depending on the deviceID the correct arduino will perform the command.
To be able to determine the deviceID i want to split that string on the ",".
this is my problem, i know how to do this easily in java (even by not using the standard split function), however in C it's a totally different story.
Can any of you guys tell me how to get this working?
thanks
/*
Serial Event example
When new serial data arrives, this sketch adds it to a String.
When a newline is received, the loop prints the string and
clears it.
A good test for this is to try it with a GPS receiver
that sends out NMEA 0183 sentences.
Created 9 May 2011
by Tom Igoe
This example code is in the public domain.
http://www.arduino.cc/en/Tutorial/SerialEvent
*/
String inputString; // a string to hold incoming data
boolean stringComplete = false; // whether the string is complete
String[] receivedData;
void setup() {
// initialize serial:
Serial.begin(9600);
// reserve 200 bytes for the inputString:
inputString.reserve(200);
}
void loop() {
// print the string when a newline arrives:
if (stringComplete) {
Serial.println(inputString);
// clear the string:
inputString = "";
stringComplete = false;
}
}
/*
SerialEvent occurs whenever a new data comes in the
hardware serial RX. This routine is run between each
time loop() runs, so using delay inside loop can delay
response. Multiple bytes of data may be available.
*/
void serialEvent() {
while (Serial.available()) {
// get the new byte:
char inChar = (char)Serial.read();
if (inChar == '\n') {
stringComplete = true;
}
// add it to the inputString:
if(stringComplete == false) {
inputString += inChar;
}
// if the incoming character is a newline, set a flag
// so the main loop can do something about it:
}
}
String[] splitCommand(String text, char splitChar) {
int splitCount = countSplitCharacters(text, splitChar);
String returnValue[splitCount];
int index = -1;
int index2;
for(int i = 0; i < splitCount - 1; i++) {
index = text.indexOf(splitChar, index + 1);
index2 = text.indexOf(splitChar, index + 1);
if(index2 < 0) index2 = text.length() - 1;
returnValue[i] = text.substring(index, index2);
}
return returnValue;
}
int countSplitCharacters(String text, char splitChar) {
int returnValue = 0;
int index = -1;
while (index > -1) {
index = text.indexOf(splitChar, index + 1);
if(index > -1) returnValue+=1;
}
return returnValue;
}
I have decided I'm going to use the strtok function.
I'm running into another problem now. The error happened is
SerialEvent.cpp: In function 'void splitCommand(String, char)':
SerialEvent:68: error: cannot convert 'String' to 'char*' for argument '1' to 'char* strtok(char*, const char*)'
SerialEvent:68: error: 'null' was not declared in this scope
Code is like,
String inputString; // a string to hold incoming data
void splitCommand(String text, char splitChar) {
String temp;
int index = -1;
int index2;
for(temp = strtok(text, splitChar); temp; temp = strtok(null, splitChar)) {
Serial.println(temp);
}
for(int i = 0; i < 3; i++) {
Serial.println(command[i]);
}
}
This is an old question, but i have created some piece of code that may help:
String getValue(String data, char separator, int index)
{
int found = 0;
int strIndex[] = {0, -1};
int maxIndex = data.length()-1;
for(int i=0; i<=maxIndex && found<=index; i++){
if(data.charAt(i)==separator || i==maxIndex){
found++;
strIndex[0] = strIndex[1]+1;
strIndex[1] = (i == maxIndex) ? i+1 : i;
}
}
return found>index ? data.substring(strIndex[0], strIndex[1]) : "";
}
This function returns a single string separated by a predefined character at a given index. For example:
String split = "hi this is a split test";
String word3 = getValue(split, ' ', 2);
Serial.println(word3);
Should print 'is'. You also can try with index 0 returning 'hi' or safely trying index 5 returning 'test'.
Hope this help!
Implementation:
int sa[4], r=0, t=0;
String oneLine = "123;456;789;999;";
for (int i=0; i < oneLine.length(); i++)
{
if(oneLine.charAt(i) == ';')
{
sa[t] = oneLine.substring(r, i).toInt();
r=(i+1);
t++;
}
}
Result:
// sa[0] = 123
// sa[1] = 456
// sa[2] = 789
// sa[3] = 999
For dynamic allocation of memory, you will need to use malloc, ie:
String returnvalue[splitcount];
for(int i=0; i< splitcount; i++)
{
String returnvalue[i] = malloc(maxsizeofstring * sizeof(char));
}
You will also need the maximum string length.
The C way to split a string based on a delimiter is to use strtok (or strtok_r).
See also this question.
I think your idea is a good start point. Here is a code that i use (to parse HTTP GET REST requests with an Ethernet shield).
The idea is to use a while loop and lastIndexOf of and store the strings into an array (but your could do something else).
"request" is the string you want to parse (for me it was called request because.. it was).
int goOn = 1;
int count = -1;
int pos1;
int pos2 = request.length();
while( goOn == 1 ) {
pos1 = request.lastIndexOf("/", pos2);
pos2 = request.lastIndexOf("/", pos1 - 1);
if( pos2 <= 0 ) goOn = 0;
String tmp = request.substring(pos2 + 1, pos1);
count++;
params[count] = tmp;
// Serial.println( params[count] );
if( goOn != 1) break;
}
// At the end you can know how many items the array will have: count + 1 !
I have used this code successfully, but i thing their is an encoding problem when i try to print params[x]... i'm alos a beginner so i don't master chars vs string...
Hope it helps.
I believe this is the most straight forward and quickest way:
String strings[10]; // Max amount of strings anticipated
void setup() {
Serial.begin(9600);
int count = split("L,-1,0,1023,0", ',');
for (int j = 0; j < count; ++j)
{
if (strings[j].length() > 0)
Serial.println(strings[j]);
}
}
void loop() {
delay(1000);
}
// string: string to parse
// c: delimiter
// returns number of items parsed
int split(String string, char c)
{
String data = "";
int bufferIndex = 0;
for (int i = 0; i < string.length(); ++i)
{
char c = string[i];
if (c != ',')
{
data += c;
}
else
{
data += '\0';
strings[bufferIndex++] = data;
data = "";
}
}
return bufferIndex;
}

Replacing spaces with %20 in C

I am writing a fastcgi application for my site in C. Don't ask why, leave all that part.
Just help me with this problem- I want to replace spaces in the query string with %20.
Here's the code I'm using, but I don't see 20 in the output, only %. Where's the problem?
Code:
unsigned int i = 0;
/*
* Replace spaces with its hex %20
* It will be converted back to space in the actual processing
* They make the application segfault in strtok_r()
*/
char *qstr = NULL;
for(i = 0; i <= strlen(qry); i++) {
void *_tmp;
if(qry[i] == ' ') {
_tmp = realloc(qstr, (i + 2) * sizeof(char));
if(!_tmp) error("realloc() failed while allocting string memory (space)\n");
qstr = (char *) _tmp;
qstr[i] = '%'; qstr[i + 1] = '2'; qstr[i + 2] = '0';
} else {
_tmp = realloc(qstr, (i + 1) * sizeof(char));
if(!_tmp) error("realloc() failed while allocating string memory (not space)\n");
qstr = (char *) _tmp;
qstr[i] = qry[i];
}
}
In the code, qry is char *, comes as a actual parameter to the function.
I tried with i + 3, 4, 5 in realloc() in the space replacer block, no success.
String-handling in C can be tricky. I'd suggest going through the string first, counting the spaces, and then allocating a new string of the appropriate size (original string size + (number of spaces * 2)). Then, loop through the original string, maintaining a pointer (or index) to the position in both the new string and the original one. (Why two pointers? Because every time you encounter a space, the pointer into the new string will get two characters ahead of the pointer into the old one.)
Here's some code that should do the trick:
int new_string_length = 0;
for (char *c = qry; *c != '\0'; c++) {
if (*c == ' ') new_string_length += 2;
new_string_length++;
}
char *qstr = malloc((new_string_length + 1) * sizeof qstr[0]);
char *c1, *c2;
for (c1 = qry, c2 = qstr; *c1 != '\0'; c1++) {
if (*c1 == ' ') {
c2[0] = '%';
c2[1] = '2';
c2[2] = '0';
c2 += 3;
}else{
*c2 = *c1;
c2++;
}
}
*c2 = '\0';
qstr[i] = '%'; qstr[i + 1] = '2'; qstr[i + 2] = '0';
That line writes three characters to your output buffer, so the next character you write needs to be written at qstr[i+3]. However, you only step i by 1, so the next character is written to qstr[i+1], overwriting the '2'.
You will need to keep separate indexes for stepping through qry & qstr.
I agree with David.
It is advisable to do it in two-steps: in the first loop you just count the spaces:
int spaceCounter=0;
const int sourceLen = strlen(qry);
for(int i = 0; i < sourceLen; ++i)
if ( qry[i] == ' ')
++spaceCounter;
char* newString = (char*)malloc(sourceLen + 3*spaceCounter*sizeof(char) + 1)
//check for null!
for(int i = 0; i < sourceLen; ++i)
if ( qry[i] == ' ')
{
*newString++ = '%';
*newString++ = '2';
*newString++ = '0';
}
else
*newString++ = qry[i];
*newString = '\0';
Warning: code not tested.
You are assigning using the same counter I you will need to have 2 counters since the strings have different lengths
your else case assigns qstr[i] = qry[i]; after you have written the %20 you are at least off by 2 on the result string.
This is known as url encode. You can refer to this page to see some similar implementation: http://www.geekhideout.com/urlcode.shtml
char* toHexSpace(const char *s)
{
char *b=strcpy(malloc(3*strlen(s)+1),s),*p;
while( p=strchr(b,' ') )
{
memmove(p+3,p+1,strlen(p));
strncpy(p,"%20",3);
}
return b;
}
needs "free" in calling context.

Resources