I wrote a function in which I want to pass a pointer to array of structures. I donew() inside it and I want to fill it with data retrieved from PGresult structure (res). However I got errors:
column number 0 is out of range 0..-1
column number 1 is out of range 0..-1
column number 2 is out of range 0..-1
column number 3 is out of range 0..-1
Segmentation fault (core dumped)
here is my function
Database::selectAnnouncements(const int user_id, const char *cat_id, struct announcementStruct **pStruct, int *size) {
*size = PQntuples(res);
struct announcementStruct * ann = new struct announcementStruct[PQntuples(res)];
*pStruct = ann;
int cr_fnum = PQfnumber(res, "created_on");
int con_fnum = PQfnumber(res, "content");
int cat_fnum = PQfnumber(res, "category");
int rm_fnum = PQfnumber(res, "remove_on");
for (int i = 0; i < PQntuples(res); i++) {
const char *cr_val = PQgetvalue(res, i, cr_fnum);
const char *con_val = PQgetvalue(res, i, con_fnum);
const char *cat_val = PQgetvalue(res, i, cat_fnum);
const char *rm_val = PQgetvalue(res, i, rm_fnum);
(*pStruct[i]).creation_date = new char[strlen(cr_val)];
(*pStruct[i]).content = new char[strlen(con_val)];
(*pStruct[i]).category = new char[strlen(cat_val)];
(*pStruct[i]).removal_date = new char[strlen(rm_val)];
strcpy((*pStruct[i]).creation_date, cr_val);
strcpy((*pStruct[i]).content, con_val);
strcpy((*pStruct[i]).category, cat_val);
strcpy((*pStruct[i]).removal_date, rm_val);
}
for (int i = 0; i < PQntuples(res); i++) {
printf("%s ", (pStruct[i]->creation_date));
printf(" %s ", (pStruct[i]->content));
printf(" %s ", (pStruct[i]->category));
printf(" %s ", (pStruct[i]->removal_date));
printf("\n");
}
PQclear(res);
}
here is how I use it
struct announcementStruct *announcements = NULL;
int size;
db.selectAnnouncements(0, "DOGS", &announcements, &size);
You are definitely forgetting to null terminate the strings. Allocate strlen + 1 to fit the null. Forgetting a null is an easy cause of segfaults. Functions like strncpy snprintf help ensure things are safer.
The comment by Kevin is also correct. Make sure you get all 12 instances of this mistake (the original 4, the four in the strcpy and the 4 in the printf)
Related
I have written a program that sets up a client/server TCP socket over which the user sends an integer value to the server through the use of a terminal interface. On the server side I am executing byte commands for which I need hex values stored in my array.
sprint(mychararray, %X, myintvalue);
This code takes my integer and prints it as a hex value into a char array. The only problem is when I use that array to set my commands it registers as an ascii char. So for example if I send an integer equal to 3000 it is converted to 0x0BB8 and then stored as 'B''B''8' which corresponds to 42 42 38 in hex. I have looked all over the place for a solution, and have not been able to come up with one.
Finally came up with a solution to my problem. First I created an array and stored all hex values from 1 - 256 in it.
char m_list[256]; //array defined in class
m_list[0] = 0x00; //set first array index to zero
int count = 1; //count variable to step through the array and set members
while (count < 256)
{
m_list[count] = m_list[count -1] + 0x01; //populate array with hex from 0x00 - 0xFF
count++;
}
Next I created a function that lets me group my hex values into individual bytes and store into the array that will be processing my command.
void parse_input(char hex_array[], int i, char ans_array[])
{
int n = 0;
int j = 0;
int idx = 0;
string hex_values;
while (n < i-1)
{
if (hex_array[n] = '\0')
{
hex_values = '0';
}
else
{
hex_values = hex_array[n];
}
if (hex_array[n+1] = '\0')
{
hex_values += '0';
}
else
{
hex_values += hex_array[n+1];
}
cout<<"This is the string being used in stoi: "<<hex_values; //statement for testing
idx = stoul(hex_values, nullptr, 16);
ans_array[j] = m_list[idx];
n = n + 2;
j++;
}
}
This function will be called right after my previous code.
sprint(mychararray, %X, myintvalue);
void parse_input(arrayA, size of arrayA, arrayB)
Example: arrayA = 8byte char array, and arrayB is a 4byte char array. arrayA should be double the size of arrayB since you are taking two ascii values and making a byte pair. e.g 'A' 'B' = 0xAB
While I was trying to understand your question I realized what you needed was more than a single variable. You needed a class, this is because you wished to have a string that represents the hex code to be printed out and also the number itself in the form of an unsigned 16 bit integer, which I deduced would be something like unsigned short int. So I created a class that did all this for you named hexset (I got the idea from bitset), here:
#include <iostream>
#include <string>
class hexset {
public:
hexset(int num) {
this->hexnum = (unsigned short int) num;
this->hexstring = hexset::to_string(num);
}
unsigned short int get_hexnum() {return this->hexnum;}
std::string get_hexstring() {return this->hexstring;}
private:
static std::string to_string(int decimal) {
int length = int_length(decimal);
std::string ret = "";
for (int i = (length > 1 ? int_length(decimal) - 1 : length); i >= 0; i--) {
ret = hex_arr[decimal%16]+ret;
decimal /= 16;
}
if (ret[0] == '0') {
ret = ret.substr(1,ret.length()-1);
}
return "0x"+ret;
}
static int int_length(int num) {
int ret = 1;
while (num > 10) {
num/=10;
++ret;
}
return ret;
}
static constexpr char hex_arr[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
unsigned short int hexnum;
std::string hexstring;
};
constexpr char hexset::hex_arr[16];
int main() {
int number_from_file = 3000; // This number is in all forms technically, hex is just another way to represent this number.
hexset hex(number_from_file);
std::cout << hex.get_hexstring() << ' ' << hex.get_hexnum() << std::endl;
return 0;
}
I assume you'll probably want to do some operator overloading to make it so you can add and subtract from this number or assign new numbers or do any kind of mathematical or bit shift operation.
example code:
const char* list[] = {"Elem_E", "Elem_T", "Elem_R", "Turtle", "Rabbit"};
const char ** patterns=0;
.
.
.
bool sec_run = false;
patterns = list;
process_data(patterns, sec_run);
process_data function:
process_data(const char **& pattern, bool sec_run){
.
.
some_variable=0;
for(int i; i < num_patterns;++i){
if(!sec_run){
some_variable = *pattern[i];
}
else{
if(/* list element contains "_" */)continue;
some_variable= /*letter after "_" */
}
if(some_variable == 'E') multiplier = 0;
else if(some_variable == 'T') multiplier = 1;
else if(some_variable == 'R') multiplier = 2;
}
}
So there is the base of what I'm trying to do. I cannot change signature for process_data. To start i do not get how some_variable = *pattern[i]; returns E,T, or R, and I cannot figure out how to iteratively access the full elements in the list. ie "Elem_E" to check for underscore and parse off the E.
I have little background in C++, but have used C numerous times. I am having a difficult time finding visual representation for char **& to help with based understanding of what is going on here, if you can point in the direction of a good tutorial with visual that will also suffice.
Sorry for confusion, forgot quotes in the list.
In C++, reading a parameter passed by reference (with the &) works the same as reading a parameter passed by value (without the &). The difference happens when you assign to the parameter. If the parameter was passed by value then the assignment is only visible inside the function but if it was passed by reference the assignment will be visible outside.
int mynumber = 0;
void foo(int &x)
{
printf("%d\n", x); //prints 0;
x = 10;
}
int main()
{
foo(mynumber);
printf("%d\n", mynumber); // prints 10
}
The equivalent to this in plain C would be to make the x parameter into a pointer and add the required *s and &s:
int mynumber = 0;
void foo(int *x)
{
printf("%d\n", *x);
*x = 10;
}
int main()
{
foo(&mynumber);
printf("%d\n", mynumber); // prints 10
}
Coming back to your code, I don't really know how to solve all your problems (what does the constant Elem_E mean? Is your list NULL terminated or is there a length stored somewhere?) but what I can say is that as long as you don't want to change the patterns global variable from inside process_data, using a char **& will be the same as using a char **.
I don't know how some_variable and multiplier will be used, but I made these changes to calculate them for each string in the list. The variable sec_run is not required in this approach. If no match is found, some_variable and multiplier are set to default values of '\0' and -1.
Output:
item=Elem_E some_variable=E multiplier=0
item=Elem_T some_variable=T multiplier=1
item=Elem_R some_variable=R multiplier=2
item=Turtle some_variable= multiplier=-1
item=Rabbit some_variable= multiplier=-1
Code:
void process_data(const char **& pattern, int num_patterns)
{
const char * item;
for (int i = 0; i < num_patterns; ++i)
{
item = pattern[i];
if ( item == NULL ) continue;
char some_variable = '\0'; // set to default for no match
int multiplier = -1; // set to default for no match
int len = strlen(item);
for (int j = 0; j < len; ++j)
{
if (item[j] == '_' && j + 1 < len)
some_variable = item[j + 1]; /*letter after "_" */
}
if (some_variable == 'E') multiplier = 0;
else if (some_variable == 'T') multiplier = 1;
else if (some_variable == 'R') multiplier = 2;
cout << "item=" << item << " some_variable=" << some_variable << " multiplier=" << multiplier << endl;
}
}
void pattern_test()
{
const char* list[] = { "Elem_E", "Elem_T", "Elem_R", "Turtle", "Rabbit" };
const char ** patterns = list;
// trick to calculate array length
// length of entire array divided by length of one element
int num_length = sizeof(list) / sizeof(list[0]);
process_data(patterns, num_length);
}
I am trying to copy a 2d character array into another 2d character array using the string function strcpy but it's giving me the error of access violation. I don't know what is it that I am doing wrong. I am posting the code and error can somebody tell me what is it that I am doing wrong
int searching(char *name[],char * namesearched,int size)
{
int count =0;
int start = 0;
int end = count;
for(;start<=end;)
{
int mid = (start + end)/2;
if(strcmp(namesearched,name[mid])==0)
{
return mid;
}
else if(strcmp(namesearched,name[mid])==1)
{
end=mid -1;
}
else if(strcmp(namesearched,name[mid])==-1)
{
start = mid +1;
}
}
return -1;
}
void sorting(char **name,char ** meaning,int count)
{
for (int i=0;i<count;i++)
{
for(int j=i+1; j<count; j++)
{
char tempname[100];
char tempmeaning[100];
if(strcmp(name[j-1],name[j])>0)
{
strcpy(tempname,name[j]);
//strcpy(name[j],tempname);
strcpy(name[j-1],name[j]);
strcpy(name[j],name[j-1]);
strcpy(name[j-1],tempname);
strcpy(tempmeaning,meaning[j]);
strcpy(meaning[j],meaning[j-1]);
strcpy(meaning[j-1], tempmeaning);
}
}
}
}
void main()
{
int size=60;
int count=0;
char namesearched[100];
cout << "Enter the name to be searched: ";
cin.getline(namesearched , 100);
char** name= new char * [size];
char** meaning = new char * [size];
for(int i=0;i < size ; i++)
{
name[i]= new char [100];
meaning[i]= new char[100];
count ++;
}
name[0] = "Journalist";
name[1] = "Blister";
name[2] = "List";
name[3] = "Listen";
name[4] = "Novelist";
name[5] = "Song";
name[6] = "Eat";
name[7] = "West";
name[8] = "Idealist";
name[9] = "Industry";
name[10] = "Legalist";
name[11] = "Write";
name[12] = "Medal";
name[13] = "Nation";
name[14] = "Accident";
name[15] = "Nest";
name[16] = "Bird";
name[17] = "Animal";
name[18] = "Lion";//wrong
name[19] = "Pigeon";
name[20] = "Real";
name[21] = "Accept";
name[22] = "Ability";
name[23] = "Bald";
name[24] = "Backbite";
name[25] = "Wakeful";
name[26] = "Absolute";
name[27] = "Wail";
name[28] = "Abiding";
name[29] = "Unacceptable";
name[30] = "Tacker";
name[31] = "Vain";//wrong
name[32] = "Abolish";
name[33] = "Taking";
name[34] = "Unarmed";
name[35] = "Habit";
name[36] = "Notus";
name[37] = "Impecle";
name[38] = "Accelerate";
name[39] = "Agony";
name[40] = "Sulk";
name[41] = "Nowise";
name[42] = "Hypocrisy";
name[43] = "Nape";
name[44] = "Eccentric";
name[45] = "Naturally";
name[46] = "Gratitude";
name[47] = "Mesmerizing";
name[48] = "Epic";
name[49] = "Abstain";
name[50] = "Enactment";
name[51] = "Hammock";
name[52] = "Nodal";
name[53] = "Laborious";
name[54] = "Nonverbal";
name[55] = "Haggle";
name[56] = "Notorious";
name[57] = "Lagger";
name[58] = "Pathetic";
name[59] = "Norms";
meaning[0] = "Sahaafi";
meaning[1] = "Chaala";
meaning[2] = "Fehrist";
meaning[3] = "Sunna";
meaning[4] = "Naval Nigaar";
meaning[5] = "Ganna";
meaning[6] = "Khanna";
meaning[7] = "Maghrib";
meaning[8] = "Tadawuri";
meaning[9] = "Sannat";
meaning[10] = "Zabta Parast";
meaning[11] = "Likhna";
meaning[12] = "Tangha";
meaning[13] = "Qoom";
meaning[14] = "Hadsa";
meaning[15] = "Ghonsla";
meaning[16] = "Parinda";
meaning[17] = "Janwar";
meaning[18] = "Shair";
meaning[19] = "Kabootar";
meaning[20] = "Haqeekat";
meaning[21] = "Qabool";
meaning[22] = "Kabliyat";
meaning[23] = "Ganja";
meaning[24] = "Ghebat Karna";
meaning[25] = "Jagta";
meaning[26] = "Bikul";
meaning[27] = "Gham Karna";
meaning[28] = "Mustakil";
meaning[29] = "NaGawar";
meaning[30] = "Jorna Wala";
meaning[31] = "Gari";
meaning[32] = "Rad kar dena";
meaning[33] = "Dil-chasp";
meaning[34] = "Nehatta";
meaning[35] = "Addat";
meaning[36] = "Dakni hawwa";
meaning[37] = "Rokna";
meaning[38] = "Taiz karna";
meaning[39] = "Sakht Takleef";
meaning[40] = "Roth Jana";
meaning[41] = "Hargiz Nahi";
meaning[42] = "Naffaq";
meaning[43] = "Mankaa";
meaning[44] = "Sanki";
meaning[45] = "Fitratan";
meaning[46] = "Tashakur";
meaning[47] = "Mashoor Karna";
meaning[48] = "Razmiya";
meaning[49] = "Baaz Rakhna";
meaning[50] = "Nifaaz";
meaning[51] = "Jholay ki tarhan ka Bichona";
meaning[52] = "Gutheela";
meaning[53] = "Mehnat Talab";
meaning[54] = "Ghair Lafzey";
meaning[55] = "Takrar Karna";
meaning[56] = "Badnam";
meaning[57] = "Ahista Chalnay walla";
meaning[58] = "Intehai afsoos naak baat";
meaning[59] = "Mayar";
int mid;
sorting( name , meaning , count);
int mid = searching(name,namesearched,count);
if( mid == -1 )
{
char ** tempname = new char* [60];
char ** tempmeaning = new char*[60];
if(count == size)
{
int increase =(10 * size)/100;
size = increase + size;
for(int i=0 ; i<size ; i++)
{
tempname[i] = new char [100];
tempmeaning[i]= new char [100];
}
for(int i = 0; i<count ; i++)
{
strcpy(tempname[i],name[i]);
strcpy(tempmeaning[i],meaning[i]);
}
}
strcpy(tempname[count] , namesearched);
cin >> tempmeaning[count];
count ++;
sorting( tempname , tempmeaning , count);
for (int i =0;i < count ;i++)
{
delete [] name[i];
delete [] meaning[i];
}
//delete [] name;
//delete [] meaning;
name = tempmeaning;
meaning = tempmeaning;
tempmeaning = NULL ;
tempname = NULL;
}
else
{
cout <<"The meaning of " << namesearched << " is: " << meaning[mid] << endl;
}
_getch();
}
Access violation writing location 0x001fbe5c.
The value of count and size is 60
One thing more strcpy works on this line strcpy(tempname , name[j]) but when it encounter this line strcpy(name[j] , name[j-1]) it throws me the error of access violation
This function declaration
void sorting(char *name[],char *meaning[],int size,int count);
does not deal with two-dimensional arrays.
For example if you have two-dimensional arrays like this
char name[60][100];
char meaning[60][100];
then the function declaration will look like
void sorting( char name[60][100], char meaning[60][100], size_t count );
or
void sorting( char name[][100], char meaning[][100], size_t count );
or
void sorting( char ( *name )[100], char ( *meaning )[100], size_t count );
and the value of the argument for the third parameter should be equal to 60.
As for your function declaration then for example this parameter char *name[]
has type of incomplete one-dimensional array of pointers of type char * that is adjusted to type char **. And if the corresponding argument is an array of pointers to string literals then the function has undefined behavior because you may not change string literals.
So it seems you are processing the arrays incorrectly that is their definitions do not correspond to the logic of the function code.
Also parameter size is not used in the function.
Thus your code simply wrong initially.
Take into account that the condition in this if statement
if(strcmp(name[j-1],name[j]))
should look either like
if ( strcmp( name[j-1], name[j] ) > 0 )
if you want to sort the arrays in the ascending order or like
if ( strcmp( name[j-1], name[j] ) < 0 )
if you want to sort the arrays in the descending order.
EDIT: After you appended your question then it is seen that 1) there are memory leaks because the pointers that initially pointed to the allocated memory are reassigned with addresses of string literals and 2) you are trying to change string literals that are immutable.
Instead of for example
name[0] = "Journalist";
you have to write
strcpy( name[0], "Journalist" );
You don't need 2d char arrays, just array of strings. So you can do it without using strcpy. Something like:
void sorting(char *name[],char *meaning[], int count)
{
for (int i = 0; i < count; i++)
{
for(int j = 1; j < count - i; j++)
{
char *tempname;
char *tempmeaning;
if(strcmp(name[j-1],name[j]) > 0)
{
tempname = name[j];
name[j] = name[j-1];
name[j-1] = tempname;
tempmeaning = meaning[j];
meaning[j] = meaning[j-1];
meaning[j-1] = tempmeaning;
}
}
}
}
char *name[] is an array of pointers to char. Pointer to char can be interpreted like a pointer to the first element of array of chars (to string). So if you want to swap two strings in array, you just need to swap pointers to that strings.
So essentially with the libraries that i'm working with I cannot use std::string, as it uses a somewhat depreciated version of C++ I need to convert this xor function from using std::string to just using char or char *. I have been trying but I cannot figure out what I am doing wrong, as I get an error. Here is the code:
string encryptDecrypt(string toEncrypt) {
char key[] = "DSIHKGDSHIGOK$%#%45434etG34th8349ty"; //Any chars will work
string output = toEncrypt;
for (int i = 0; i < toEncrypt.size(); i++)
output[i] = toEncrypt[i] ^ key[i % (sizeof(key) / sizeof(char))];
return output;
}
If anyone could help me out, that would be great. I am unsure as to why I cannot do it by simply changing the strings to char *.
Edit:
What I have tried is:
char * encryptDecrypt(char * toEncrypt) {
char key[] = "DSIHKGDSHIGOK$%#%45434etG34th8349ty"; //Any chars will work
char * output = toEncrypt;
for (int i = 0; i < sizeof(toEncrypt); i++)
output[i] = toEncrypt[i] ^ key[i % (sizeof(key) / sizeof(char))];
return output;
}
Please note I am not trying to convert an std::string to char, I simply cannot use std::string in any instance of this function. Therefore, my question is not answered. Please read my question more carefully before marking it answered...
The issue here is
char * output = toEncrypt;
This is making output point to toEncrypt which is not what you want to do. What you need to do is allocate a new char* and then copy the contents of toEncrypt into output
char * encryptDecrypt(char * toEncrypt) {
char key[] = "DSIHKGDSHIGOK$%#%45434etG34th8349ty"; //Any chars will work
int string_size = std::strlen(toEncrypt);
char * output = new char[string_size + 1]; // add one for the null byte
std::strcpy(output, toEncrypt); //copy toEncrypt into output
for (int i = 0; i < string_size; i++)
output[i] = toEncrypt[i] ^ key[i % (sizeof(key) / sizeof(char))];
return output;
}
Live Example
Since we are using dynamic memory allocation here we need to make sure that the caller deletes the memory when done otherwise it will be a memory leak.
sizeof() is a compile-time operator that evaluates the size of the type of its argument. When you do sizeof(toEncrypt), you're really just doing sizeof(char*) -- not the length of the string, which is what you want. You'll need to somehow indicate how long the toEncrypt string is. Here are two possible solutions:
Add an integer argument to encryptDecrypt specifying the length of toEncrypt in characters.
If you know that toEncrypt will never contain the null byte as a valid character for encryption / decryption (not sure of your application) and can assume that toEncrypt is null-terminated, you could use the strlen function to determine string length at runtime.
I'd recommend option 1, as strlen can introduce security holes if you're not careful, and also because it allows the use of null bytes within your string arguments.
What error are you getting? You can easily use a char* to do the same thing, I've included a sample program that verifies the functionality. This was built under VS2012.
#include <string>
#include <stdio.h>
std::string encryptDecrypt( std::string toEncrypt)
{
char key[] = "DSIHKGDSHIGOK$%#%45434etG34th8349ty"; //Any chars will work
std::string output = toEncrypt;
for (int i = 0; i < toEncrypt.size(); i++)
output[i] = toEncrypt[i] ^ key[i % (sizeof(key) / sizeof(char))];
return output;
}
void encryptDecrypt( char* toEncrypt )
{
char key[] = "DSIHKGDSHIGOK$%#%45434etG34th8349ty"; //Any chars will work
int len = strlen( toEncrypt );
for (int i = 0; i < len; i++)
toEncrypt[i] = toEncrypt[i] ^ key[i % (sizeof(key) / sizeof(char))];
}
int main( int argc, char* argv[] )
{
const char* sample = "This is a sample string to process";
int len = strlen( sample );
char* p = new char[ len + 1 ];
p[len] = '\0';
strcpy( p, sample );
std::string output = encryptDecrypt( sample );
encryptDecrypt( p );
bool match = strcmp(output.c_str(), p) == 0;
printf( "The two encryption functions %smatch.\n", match ? "" : "do not " );
return 0;
}
Why not instead of string output = toEncrypt :
char *output = new char[std::strlen(toEncrypt) + 1];
std::strcpy(output, toEncrypt);
I am currently using this approach to copy some byte values over:
for (int i = 0; i < (iLen + 1); i++)
{
*(pBuffer + i) = Image.pVid[i];
}
I would like to ask if there is a way to copy these values over in one go, perhaps by using memcopy to gain more speed.
The entire code is:
extern "C" __declspec(dllexport) int __stdcall GetCameraImage(BYTE pBuffer[], int Type, int uWidth, int uHeight)
{
CameraImage Image;
int ret;
Image.pVid = (unsigned int*)malloc(4 * uWidth*uHeight);
ret = stGetCameraImage(&Image, 1, uWidth, uHeight);
if (ret == ERR_SUCCESS)
{
int iLen = (4 * uWidth * uHeight);
for (int i = 0; i < (iLen + 1); i++)
{
*(pBuffer + i) = Image.pVid[i];
}
////print(“ImageType = %d, width = %d, height = %d”, Image.Type, Image.Width,
//// Image.Height);
////print(“First Pixel : B = %d, G = %d, R = %d”, Image.pVid[0], Image.pVid[1],
//// Image.pVid[2]);
////print(“Second Pixel : B = %d, G = %d, R = %d”, Image.pVid[4], Image.pVid[5],
//// Image.pVid[6]);
}
free(Image.pVid);
return ret;
}
Edit:
*pVid is this:
unsigned int *pVid; // pointer to image data (Format RGB32...)
The way your code is currently written, each assignment in your loop will overflow and give you some garbage value in pBuffer because you're trying to assign an unsigned int to a BYTE. On top of that, you will run off the end of the Image.pVid array because i is counting bytes, not unsigned ints
You could fix your code by doing this:
*(pBuffer + i) = ((BYTE*)Image.pVid)[i];
But that is pretty inefficient. Better to move whole words at a time, or you could just use memcpy instead:
memcpy(pBuffer,Image.pVid,iLen) //pBuffer must be at least iLen bytes long