how do remove enclosing brackets from string? [closed] - c

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I have a
char s9[7] = "[abcd]";
How do i remove the brackets [] so that
s9 == "abcd"
I have tried
s9 = s9.Substring(1, s9.Length-2);
throws error in cygwin
a2v2.c:42:13: error: request for member ‘Substring’ in something not a structure or union
a2v2.c:42:29: error: request for member ‘Length’ in something not a structure or union
edit:
i realised my error, i am beginner at c and couldnt differentiate between c and C++ code, regards

Someone will correct me if I'm wrong, since the C standard I know is a couple of decades old, but as far as I know, C doesn't offer any standard support for string manipulation, and in fact doesn't even officially have a concept of strings. (Or of object functions, for that matter.) Instead, C uses pointers, which are much more powerful, but much more dangerous in that you can really mess things up if you don't learn your way around them.
The most important thing, if you want to be a C programmer is that you learn C. At the very least, you need to look up "string manipulation C" and read any of the pages that pop up.
There are many ways to do what you want. I think this is one of the faster ones (though it modifies the string you're looking at. If that matters, choose another way):
// trim off the last character
s9[strlen(s9) - 1] = '\0';
// the char * points to the s9 array. +1 makes it look at
// the second element, so then substring is the string you need
char * substring = s9 + 1;

Skipping any checking that the string actually begins and ends with those characters:
int len = strlen(s9);
for ( i = 0; i < len - 2; ++i )
s9[i] = s9[i + 1];
s9[len - 2] = '\0';

memmove( s9, s9 + 1, 4);
s9[4] = 0;

If it is strictly C, then you will need to use more basic functions (a char[] array has little in common with the string class in C++). Some of the functions to use might be:
strchr: Find the position of a character (e.g., strchr( s9, '[')). This assumes that it is not a fixed format you are dealing with. If you know the length and positions, then you could skip this and simply use memmove directly.
memmove: Shift the character left in the array. In this situation memmove would be needed (over memcpy or strncpy) because the target and destination overlap.

int len = strlen(s9);
memmove(s9, (s9+1), len-2); /* can handle overlapping strings */
s9[len-2] = 0; /* null terminate */

Related

Why no split function in C? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
There is no Standard function in C to take a string, break it up at whitespace
or other delimiters, and create an array of pointers to char, in one step.
If you want to do that sort of thing, you have to do it yourself, either
completely by hand, or by calling e.g. strspn and strpbrk in a loop,
or by calling strtok in a loop, or by calling strsep in a loop.
I am not asking how to do this. I know how to do this,
and there are plenty of
other questions
on Stackoverflow
about how to do it. What I'm asking is if there are any good reasons why
there's no such function.
I know the two main reasons, of course: "Because no mainstream compiler/library
ever had one" and "Because the C Standard didn't specify one, either (because
it likes to standardize existing practice)." But are there any other reasons?
(Are there arguments that such a function is an actively bad idea?)
This is usually a lame and pointless sort of question, I know. In this case
I'm fixated on it because convenient splitting is such a massively useful
operation. I wrote my own string splitter within my first year as a
C programmer, I think, and it's been a huge productivity enhancer for me ever
since. There are dozens of questions here on SO every day that could be
answered easily (or that wouldn't even have to be asked) if there were a
standard split function that everyone could use and refer to.
To be clear, the function I'm imagining would have a signature like
int split(char *string, char **argv, int maxargs, const char *delim)
It would break up string into at most maxargs substrings, splitting on one or more characters from delim, placing pointers to the substrings into argv, and modifying string in the process.
And to head off an argument I'm sure someone will make: although it's standard, I do not consider
strtok to be an effective solution. strtok, frankly, sucks. Saying "you don't need a split function,
because strtok exists" is a lot like saying "You don't need printf,
because puts exists." This is not a question about what's theoretically
possible with a given toolset; it's about what's useful and convenient. The more
fundamental issue here, I guess, concerns the ineffable tradeoffs involved
in picking tools that are leverageable and productivity-enhancing and that
"pay their way". (I think it's clear that a nicely encapsulated
string-splitting function would pay its way handsomely, but perhaps
that's just me.)
I will try an answer. I indeed agree that such a function would be usefull. It is often quite usefull in the languages that have one.
Basically you are suggesting a builtin very simple wrapper around strtok() or strtok_r(). It would be a less powefull version (as we can't change delimiter while processing) but still usefull in some cases.
What I see is that these cases are also overlapping with scanf() familly functions use cases and with getopt() or getsubopt() familly functions use cases.
Actually I'm not sure that the remaining real use cases are that common.
In real life non trivial cases you would need a true parser or regex library, in specialized common case you already have scanf() or getopt() or even strtok().
Also functions modifying their input strings like strtok() or yours are more or less deprecated these days (experience says they easily lead to troubles).
Most languages providing a split feature have a real string type, often an unmutable one, and are supporting it by creating many individual substrings while leaving the original string intact.
Following that path would lead to either some other API non based on zero delimited strings (maybe with a start pointer and and end pointer), or with allocated string copies (like when using strdup()). Neither really satisfying.
In the end, if you add up not so common use in real life, quite simple to write and not that simple or intuitive API, there is no wonder that such function wasn't included in strandard libc.
Basically I would write something like that:
#include <string.h>
#include <stdio.h>
int split(char *string, char **argv, int maxargs, const char *delim){
char * saveptr = 0;
int x = 0;
argv[x++] = strtok_r(string, delim, &saveptr);
while(argv[x-1] && (x <= maxargs)){
argv[x++] = strtok_r(0, delim, &saveptr);
}
return x-1;
}
int main(){
char * args[10];
{
char * str = strdup("un deux trois quatre cinq six sept huit neuf dix onze");
int res = split(str, args, sizeof(args)/sizeof(char*), " ");
printf("res = %d\n", res);
for(int x = 0; x < res ; x++){
printf("%d:%s\n", x, args[x]);
}
}
{
char * str = strdup("un deux trois quatre cinq");
int res = split(str, args, sizeof(args)/sizeof(char*), " ");
printf("res = %d\n", res);
for(int x = 0; x < res ; x++){
printf("%d:%s\n", x, args[x]);
}
}
}
What I see looking at the code is that the wanted function is really very simple to write using strtok()... and that the call site to use the result is nearly as complicated than the function itself. In such a case hencefore I'd rather inline the function on the call site than having to call libc.
But of course you are welcome to use and write yours if you believe it's simpler for you.

Input Loop trouble [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 7 years ago.
Improve this question
What I've done is ask a user to input how many times the program will loop, it then records values into 3 different arrays. Everything is working great, but what I need it to do is print the elements of one array if the corresponding element in another array meets the requirements. Everything else runs great, I'll post the two arrays that I'm trying to use for this.
char *names[50][32];
char *states[50][2];
i = 0;
while ( i < b) {
if (state[i] = "tx");{
printf("a string %s\n", names[i]);}
i = i + 1;
}
for this : if (state[i] = "tx");{ I've tried with and without quotes and using 116120...
Basically, it asks for peoples names and where they live. I can get it to print the array element values for each name(it runs in a loop) but I want it to only print the names for the people who live in tx.
There are a few things wrong with your code. First of all ending an if or for construction with a semicolon is a common mistake when starting in C. Basically it creates an empty if statement followed by a code block. Look at it this way:
if (condition)
; // Does nothing. The if is empty
// Totally unrelated block of code.
{
}
Code blocks are usually useful to create scopes, so although it might seem useless for the compiler to interpret blocks in this way, it actually is not. This also happens in other situations, such as while, for, and so on:
for (int i=0 ; i<n ; ++i)
; // Empty for. Runs `n` loops, but doing nothing
// Unrelated block of code. Runs only once
{
}
The comparison operator is also wrong, you should use == for comparisons, instead of =, which is used for assignments.
Finally, you cannot compare strings in this way. Strings are basically arrays, which in turn are represented using pointers. If you compare two pointers (ptr1 == ptr2) it'll only check whether the two strings point at the same address in memory. As strings are composed by several characters, they have to be iterated to be properly compared. Fortunately the standard library already provides a method for this.
Fix a typo or two and this is what you get:
char *names[50][32];
char *states[50][2];
i = 0; // Assuming this is declared somewhere else
while ( i < b) {
if (strcmp(states[i], "tx") == 0) {
printf("a string %s\n", names[i]);
}
i = i + 1;
}
You should probably also check the docs for strcmp.
Edit: as this is already the accepted answer, I should also include a fix as noted by #dbush. The array for stats is clearly missing space for the extra string terminator, as strings are NULL terminated in C. The array for names might or might not suffer from the same issue, it's not clear. Anyway, it's notable that both should include an extra byte for storing the terminator:
char names[50][33];
char states[50][3];
Props to #dbush.
The declaration of your arrays don't look correct:
char *names[50][32];
char *states[50][2];
These declare a pair of two-dimensional array of char pointers, which is probably not what you want.
char names[50][32];
char states[50][3];
These are two-dimensional arrays of characters, or alternately arrays of strings. Note that the states array has space for an extra character for the terminating NULL.
In this if statement this:
if (state[i] = "tx");{
Since the ; occurs immediately after the condition, that ends the if block. The following statements within curly braces therefore will always run. Also, = is for assignment, not comparison, but using == is not appropriate either, since that operator won't compare the strings, but their addresses. You need to use strcmp for string comparisons.
So the fixed code should look like this:
char names[50][32];
char states[50][3];
...
i = 0;
while ( i < b) {
if (strcmp(state[i],"tx") == 0) {
printf("a string %s\n", names[i]);
}
i = i + 1;
}

Is this code vulnerable to buffer overflow?

Fortify reported a buffer overflow vulnerability in below code citing following reason -
In this case we are primarily concerned with the case "Depends upon properties of the data that are enforced outside of the immediate scope of the code.", because we cannot verify the safety of the operation performed by memcpy() in abc.cpp
void create_dir(const char *sys_tmp_dir, const char *base_name,
size_t base_name_len)
{
char *tmp_dir;
size_t sys_tmp_dir_len;
sys_tmp_dir_len = strlen(sys_tmp_dir);
tmp_dir = (char*) malloc(sys_tmp_dir_len + 1 + base_name_len + 1);
if(NULL == tmp_dir)
return;
memcpy(tmp_dir, sys_tmp_dir, sys_tmp_dir_len);
tmp_dir[sys_tmp_dir_len] = FN_LIBCHAR;
memcpy(tmp_dir + sys_tmp_dir_len + 1, base_name, base_name_len);
tmp_dir[sys_tmp_dir_len + base_name_len + 1] = '\0';
..........
..........
}
It appears to me a false positive since we are getting the size of data first, allocating that much amount of space, then calling memcpy with size to copy.
But I am looking for good reasons to convince fellow developer to get rid of current implementation and rather use c++ strings. This issue has been assigned to him. He just sees this a false positive so doesn't want to change anything.
Edit I see quick, valid criticism of the current code. Hopefully, I'll be able to convince him now. Otherwise, I'll hold the baton. :)
Take a look to strlen(), it has input string but it has not an upper bound then it'll go on searching until it founds \0. It's a vulnerability because you'll perform memcpy() trusting its result (if it won't crash because of access violation while searching). Imagine:
create_dir((const char*)12345, baseDir, strlen(baseDir));
You tagged both C and C++...if you're using C++ then std::string will protect you from these issues.
It appears to me a false positive since we are getting the size of data first, allocating that much amount of space
This assumption is a problem that matches the warning/error. In your code, you're assuming that malloc successfully allocated the requested memory. If your system has no memory to spare, malloc will fail and return NULL. When you try to memcpy into tmp_dir, you'd be copying to NULL which would be bad news.
You should check to guarantee that the value returned by malloc is not NULL before considering it as a valid pointer.

Efficiency of strncpy and code [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 8 years ago.
Improve this question
I'm slowly learning and progressing through coding, so I was hoping someone could have a quick look at this function for me and tell me if it appears that I'm on the right track, how I could do it better or where I might be setting myself up for failure. I'm new to the world of C, so please take it easy on me - but be blunt and honest.
void test(char *username, char *password) {
printf("Checking password for %s - pw: %s\n",username,password);
char *query1 = "SELECT password FROM logins WHERE email = '";
char *query2 = "' LIMIT 1";
char *querystring = malloc(strlen(query1) + strlen(username) + strlen(query2) * sizeof(char));
strncpy(querystring,query1,strlen(query1));
strncat(querystring,username,strlen(username));
strncat(querystring,query2,strlen(query2));
printf("Query string: %s\n",querystring);
mysql_query(mysql_con,querystring);
MYSQL_RES *result = mysql_store_result(mysql_con);
int num_fields = mysql_num_fields(result);
int num_rows = mysql_num_rows(result);
if (num_rows != 0) {
MYSQL_ROW row;
printf("Query returned %i results with %i fields\n",num_rows,num_fields);
row = mysql_fetch_row(result);
printf("Password returned: %s\n",row[0]);
int comparison = strncmp(password, row[0], strlen(password));
if (comparison == 0) {
printf("Passwords match!\n");
} else {
printf("Passwords do NOT match!\n");
}
} else {
printf("No such user... Password is invalid");
}
free(querystring);
}
At the moment, it is working... output:
Checking password for jhall#futuresouth.us - pw: 5f4dcc3b5aa765d61d8327deb882cf99
Query string: SELECT password FROM logins WHERE email = 'test#blah.com' LIMIT 1
Query returned 1 results with 1 fields
Password returned: 5f4dcc3b5aa765d61d8327deb882cf99
Passwords match!
called with:
test("test#blah.com","5f4dcc3b5aa765d61d8327deb882cf99");
I'm looking for input on how I could have worked with the strings better, or if there are any unforeseen issues with how I did this. I'm very new to working with data structures in C.
Using strncpy(target, source, strlen(source)) guarantees that the string in target is not null terminated. If perchance malloc() returns zeroed memory, then it will seem to work, but once malloc() returns non-zeroed memory (previously allocated memory), things will go wrong.
The length argument to strncat() is just plain weird; it is the amount of space left in the target string after the current (null-terminated) data. Your usage, quite apart from not having null-terminated strings to work on, does not protect against buffer overflow.
There really isn't a good use case for strncat() IMNSHO, and seldom a good case for strncpy(). If you know how big everything is, you can use memmove() (or memcpy()) instead. If you don't know how big everything is, you don't know whether it is safe to do the copy without truncation.
Your malloc() call is a bit peculiar too: it doesn't allocate enough space for the trailing null, and it only multiplies one of the three terms by sizeof(char), which is inconsistent but otherwise harmless. A lot of the time you will get away with the short allocation because malloc() rounds the size up, but all hell will break loose when you don't get away with. A tool like valgrind will report abuse of allocated memory.
Jonathan's answer explains the problems with that part of the code.
To fix it you can use snprintf instead:
size_t space_needed = strlen(query1) + strlen(username) + strlen(query2) + 1;
char *querystring = malloc(space_needed + 1);
if ( !query_string )
exit(EXIT_FAILURE);
snprintf(query_string, space_needed, "%s%s%s", query1, username, query2);
Then, even if you calculate the length wrong, at least you didnt get a buffer overflow.
To avoid the code duplication here there is a non-standard function asprintf that you pass the arguments and it yields a pointer to a malloc'd buffer of the right size. Of course, it's possible to write your own version of this function if you don't want to rely on the existence of that function.
There's another serious issue here in that your code does not protect against SQL injection (see here for explanation). A proper discussion of how to protect against that is probably beyond the scope of this question!

How to write into a char array in C at specific location using sprintf?

I am trying to port some code written in MATLAB to C, so that I can compile the function and execute it faster (the code is executed very often and it would bring a significant speed increase).
So basically what my MATLAB code does it that it takes a matrix and converts it to a string, adding brackets and commas, so I can write it to a text file. Here's an idea of how this would work for a vector MyVec:
MyVec = rand(1,5);
NbVal = length(MyVec)
VarValueAsText = blanks(2 + NbVal*30 + (NbVal-1));
VarValueAsText([1 end]) = '[]';
VarValueAsText(1 + 31*(1:NbVal-1)) = ',';
for i = 1:NbVal
VarValueAsText(1+(i-1)*31+(1:30)) = sprintf('%30.15f', MyVec(i));
end
Now, how can I achieve a similar result in C? It doesn't seem too difficult, since I can calculate in advance the size of my string (char array) and I know the position of each element that I need to write to my memory area. Also the sprintf function exists in C. However, I have trouble understanding how to set this up, also because I don't have an environment where I can learn easily by trial and error (for each attempt I have to recompile, which often leads to a segmentation fault and MATLAB crashing...).
I hope someone can help even though the problem will probably seem trivial, but I have have very little experience with C and I haven't been able to find an appropriate example to start from...
Given an offset (in bytes) into a string, retrieving a pointer to this offset is done simply with:
char *ptr = &string[offset];
If you are iterating through the lines of your matrix to print them, your loop might look as follow:
char *ptr = output_buffer;
for (i = 0; i < n_lines; i++) {
sprintf (ptr, "...", ...);
ptr = &ptr[line_length];
}
Be sure that you have allocated enough memory for your output buffer though.
Remember that sprintf will put a string-terminator at the end of the string it prints, so if the string you "print" into should be longer than the string you print, then that won't work.
So if you just want to overwrite part of the string, you should probably use sprintf to a temporary buffer, and then use memcpy to copy that buffer into the actual string. Something like this:
char temp[32];
sprintf(temp, "...", ...);
memcpy(&destination[position], temp, strlen(temp));

Resources