I'm currently working on a server which is part of my course requirement. The specs require me to parse a request line and store the appropriate data as absolute path (abs_path) and query.
Here is my code:
bool parse(const char* line, char* abs_path, char* query)
{
int space = 0;
if (strchr(line, '"') != NULL)
{
error(400);
return false;
}
for (int i = 0; line[i] != '\0'; i++)
{
if (line[i] == ' ')
{
space++;
}
}
if (space != 2)
{
error(400);
return false;
}
if (strncmp("GET ", line, 4) != 0)
{
error(405);
return false;
}
line = strchr(line, ' ');
line++;
if (strncmp("/", line, 1) != 0)
{
error(501);
return false;
}
int j = 0;
int k = 4;
while (line[k] != ' ')
{
int m = k;
abs_path[j] = line[k];
j++;
if (line[k+1] == '?')
{
abs_path[j] = '\0';
int l = 0;
m = k+2;
while (line[m] != ' ')
{
query[l] = line[m];
l++;
m++;
}
if (line[m] == ' ' && l == 0)
{
query[0] = '\0';
}
}
k = m;
k++;
if (line[k] == ' ')
{
abs_path[j] = '\0';
break;
}
}
char* last = strrchr(line, ' ');
last++;
if (strcmp("HTTP/1.1", last) != 0)
{
error(505);
return false;
}
free(abs_path);
return true;
}
I keep getting a segmentation fault with this. After some debugging, I've found the segmentation fault to be eliminated if I declare, on line 20, abs_path as an array instead of a pointer. However, it is necessary for me to declare abs_path as a pointer, so I need another solution to this. Can someone explain to me what exactly I am doing wrong with regards to strings and their handling?
I have been quite rusty with this due to personal reasons so pardon me if I misunderstand something basic.
Thank you in advance!
You need to allocate memory for the char*. An array does this automatically during compile time. Try malloc.
char* abs_path = 0;
abs_path = (char*)malloc(256);
Essentially, malloc performs an operating system call to reserve sequential memory from the heap. The argument of malloc is how many bytes to reserve. Therefore, you should be aware that the example above enables the abs_path char* to point to a string that is at max 255 characters (leaving 1 byte for the null character '\0'). Don't let your code write more than 255 characters or you will overwrite other data in memory, which is why you received a seg-fault before.
As someone else noted, you should DEFINITELY free up memory reserved dynamically with malloc.
free(abs_path);
Related
int main ()
{
int num, i=num, isPrime;
printf("Enter an integer: ");
scanf("%d", &num);
while (i>=2)
{
if (num%i!=0)
i--;
if (num%i==0) //check if it is a factor
{
isPrime = 1;
for (int j=2; j<=i; j++)
{
if (i%j==0)
{
isPrime = 0;
break;
}
}
if (isPrime==1)
{
printf("%d ", i);
num = num/i;
}
}
}
return 0;
}
May I know why is my code not working?
I was trying to write a C code which print all prime factors of a given number from the biggest factor to the smallest and when I run it just show nothing after I input a number.
#include of required header stdio.h to use printf() and scanf() is missing.
num is assigned to i before a value is read to num. This is assigning an indeterminate value to i and using the value invokes undefined behavior.
Looping j until it becomes i is wrong because i%i will always become zero unless i is zero.
You should decrement i also when num%i==0 and i is not prime. Otherwise, the update of i will stop there and the loop may go infinitely.
The two if statements if (num%i!=0) and if (num%i==0) may see different values of i. This happens when num%i!=0 at the beginning of the iteration because i is updated when the condition is true. You should use else instead of the second if statement.
Fixed code:
#include <stdio.h>
int main (void)
{
int num, i, isPrime;
printf("Please enter an integer: ");
if (scanf("%d", &num) != 1)
{
fputs("read error\n", stderr);
return 1;
}
i=num;
while (i>=2)
{
if (num%i!=0) //check if it is a factor
{
i--;
}
else
{
isPrime = 1;
for (int j=2; j<i; j++)
{
if (i%j==0)
{
isPrime = 0;
break;
}
}
if (isPrime==1)
{
printf("%d ", i);
num = num/i;
}
else
{
i--;
}
}
}
return 0;
}
At least one bug here:
int num, i=num, isPrime;
It seems you are trying to make i equal to num. But here `num isn't even initialized yet. You have to do the assignment after reading user input:
int num, i, isPrime;
printf("Please enter an integer: ");
scanf("%d", &num);
i=num;
Also the check for primes is wrong:
for (int j=2; j<=i; j++)
{
if (i%j==0)
{
isPrime = 0;
break;
}
}
Since you use j<=i then j will eventually be equal to i and i%j==0 will be true so you don't find any primes. Try j<i instead.
When reading a JSON string from the serial port on an ESP8266 it cuts off the beginning of the data.
I have tried reading data from the Serial port and printing each character, however it is cutting off part of the begging of the data.
void setup() {
Serial.begin(115200);
while (!Serial) {
;
}
}
void loop() {
int curSize = 30;
char* buffer = new char[curSize];
std::fill_n(buffer, curSize, 0);
int pos = 0;
Serial.print("Sending: ");
while(Serial.available() == false) delay(500);
while (Serial.available()) {
char c = Serial.read();
Serial.print(c);
if(pos == curSize-1){
char* newBuffer = increaseBuffer(buffer, curSize, curSize + 30);
curSize += 30;
delete[] buffer;
buffer = newBuffer;
}
if(c == '\n'){
buffer[pos] = 0;
pos = 0;
break;
}
buffer[pos++] = c;
}
if(buffer[0] != 0) {
sendBuffer(buffer);
}
delete[] buffer;
}
char* increaseBuffer(char* orig, int oldSize, int newSize){
char* data = new char[newSize];
std::fill_n(data, newSize, 0);
for(int i = 0; i < newSize; i++){
if(i < oldSize) data[i] = orig[i];
else data[i] = '\0';
}
return data;
}
JSON data used (and expected output)
{"type":0,"ver":"0.0.1","T":[28,29,29,29,29,29,29,29,29,29],"H":[59.1608,59.1608,60,59.1608,60,60,60,59.1608,59.1608,59.1608],"DP":[20.36254,20.36254,20.59363,20.36254,20.59363,20.59363,20.59363,20.36254,20.36254],"HI":[30.90588,30.90588,31.0335,30.90588,31.0335,31.0335,31.0335,30.90588,30.90588]}
examples of what is actually output
Example 1: 9,29,29,29,29,29,29,29,29],"H":[59.1608,59.1608,60,59.1608,60,60,60,59.1608,59.1608,59.1608],"DP":[20.36254,20.36254,20.59363,20.36254,20.59363,20.59363,20.59363,20.36254,20.36254],"HI":[30.90588,30.90588,31.0335,30.90588,31.0335,31.0335,31.0335,30.90588,30.90588]}
Example 2: 29,29,29,29,29,29,29,29,29],"H":[59.1608,59.1608,60,59.1608,60,60,60,59.1608,59.1608,59.1608],"DP":[20.36254,20.36254,20.59363,20.36254,20.59363,20.59363,20.59363,20.36254,20.36254],"HI":[30.90588,30.90588,31.0335,30.90588,31.0335,31.0335,31.0335,30.90588,30.90588]}
Try making the delay 1 instead of 500 in the blocking loop that's waiting for data to start coming in. I'm going to guess what happens is that on one iteration of that loop Serial.available() is false and during the delay you start to get data coming in that ends up getting written over by the time your delay ends to check again.
What I'm picturing is the following. If you were to expand out that delay(500) to be delay(1) called 500 times.
while(Serial.available() == false){
delay(1);
delay(1);
// ...
delay(1); // first character comes in
delay(1);
delay(1); // second character comes in
// ...
delay(1); // n character comes in
}
Then after the delay is over you start actually collecting the characters that are coming in.
I have written a non recursive solution to the Ackermann function, it seems to work perfectly and work faster than the common recursive solution. So I am confused as to why it is a non primitive recursive function if it can be solved iteratively? Could anyone tell me if I have misunderstood something about what primitive recursive functions are or who should I talk to about this to get an answer?
Below is the Java code:
import java.util.Scanner;
import java.util.ArrayList;
public class ackermann {
public static void main(String[] args){
Scanner in = new Scanner(System.in);
System.out.println("Enter m:");
int m = in.nextInt();
System.out.println("Enter n:");
int n = in.nextInt();
ack(m, n);
}
public static void ack(int inM, int inN){
if(inM < 0 || inN < 0) return;
ArrayList<ArrayList<Integer>> arr = new ArrayList<ArrayList<Integer>>();
for(int m = 0; m <= inM; m++){
arr.add(new ArrayList<Integer>());
}
Boolean done = false;
while(done == false){
for(int m = 0; m <= inM; m++){
int n = arr.get(m).size();
int a = 0;
if(m == 0) a = n + 1;
else if(n == 0){
if(arr.get(m - 1).size() <= 1) break;
a = arr.get(m - 1).get(1);
} else {
int k = arr.get(m).get(n - 1);
if(arr.get(m - 1).size() <= k) break;
a = arr.get(m - 1).get(k);
}
arr.get(m).add(a);
if(m == inM && n == inN){
System.out.println("Ack(" + inM + ", " + inN + ") = " + a);
done = true;
break;
}
}
}
}
}
Primitive recursive functions can be implemented using only assignment, +, and definite loops. By this I mean loops of the form:
for(int i = 0; i < n; i++) { ... }
Where n is a variable that isn't changed in the loop body. To get Ackermann's function, which majorizes all primitive recursive functions, one needs to add either a goto command or indefinite loops like your while loop.
I'm not too good with C++, however; my code compiled, but the function crashes my program, the below is a short sum-up of the code; it's not complete, however the function and call is there.
void rot13(char *ret, const char *in);
int main()
{
char* str;
MessageBox(NULL, _T("Test 1; Does get here!"), _T("Test 1"), MB_OK);
rot13(str, "uryyb jbeyq!"); // hello world!
/* Do stuff with char* str; */
MessageBox(NULL, _T("Test 2; Doesn't get here!"), _T("Test 2"), MB_OK);
return 0;
}
void rot13(char *ret, const char *in){
for( int i=0; i = sizeof(in); i++ ){
if(in[i] >= 'a' && in[i] <= 'm'){
// Crashes Here;
ret[i] += 13;
}
else if(in[i] > 'n' && in[i] <= 'z'){
// Possibly crashing Here too?
ret[i] -= 13;
}
else if(in[i] > 'A' && in[i] <= 'M'){
// Possibly crashing Here too?
ret[i] += 13;
}
else if(in[i] > 'N' && in[i] <= 'Z'){
// Possibly crashing Here too?
ret[i] -= 13;
}
}
}
The function gets to "Test 1; Does get Here!" - However it doesn't get to "Test 2; Doesn't get here!"
Thank you in advanced.
-Nick Daniels.
str is uninitialised and it is being dereferenced in rot13, causing the crash. Allocate memory for str before passing to rot13() (either on the stack or dynamically):
char str[1024] = ""; /* Large enough to hold string and initialised. */
The for loop inside rot13() is also incorrect (infinte loop):
for( int i=0; i = sizeof(in); i++ ){
change to:
for(size_t i = 0, len = strlen(in); i < len; i++ ){
You've got several problems:
You never allocate memory for your output - you never initialise the variable str. This is what's causing your crash.
Your loop condition always evaluates to true (= assigns and returns the assigned value, == tests for equality).
Your loop condition uses sizeof(in) with the intention of getting the size of the input string, but that will actually give you the size of the pointer. Use strlen instead.
Your algorithm increases or decreases the values in the return string by 13. The values you place in the output string are +/- 13 from the initial values in the output string, when they should be based on the input string.
Your algorithm doesn't handle 'A', 'n' or 'N'.
Your algorithm doesn't handle any non-alphabetic characters, yet the test string you use contains two.
I'm interested in unescaping text for example: \ maps to \ in C. Does anyone know of a good library?
As reference the Wikipedia List of XML and HTML Character Entity References.
For another open source reference in C to decoding these HTML entities you can check out the command line utility uni2ascii/ascii2uni. The relevant files are enttbl.{c,h} for entity lookup and putu8.c which down converts from UTF32 to UTF8.
uni2ascii
I wrote my own unescape code; very simplified, but does the job: pn_util.c
Function Description: Convert special HTML entities back to characters.
Need to do some modifications to fit your requirement.
char* HtmlSpecialChars_Decode(char* encodedHtmlSpecialEntities)
{
int encodedLen = 0;
int escapeArrayLen = 0;
static char decodedHtmlSpecialChars[TITLE_SIZE];
char innerHtmlSpecialEntities[MAX_CONFIG_ITEM_SIZE];
/* This mapping table can be extended if necessary. */
static const struct {
const char* encodedEntity;
const char decodedChar;
} entityToChars[] = {
{"<", '<'},
{">", '>'},
{"&", '&'},
{""", '"'},
{"'", '\''},
};
if(strchr(encodedHtmlSpecialEntities, '&') == NULL)
return encodedHtmlSpecialEntities;
memset(decodedHtmlSpecialChars, '\0', TITLE_SIZE);
memset(innerHtmlSpecialEntities, '\0', MAX_CONFIG_ITEM_SIZE);
escapeArrayLen = sizeof(entityToChars) / sizeof(entityToChars[0]);
strcpy(innerHtmlSpecialEntities, encodedHtmlSpecialEntities);
encodedLen = strlen(innerHtmlSpecialEntities);
for(int i = 0; i < encodedLen; i++)
{
if(innerHtmlSpecialEntities[i] == '&')
{
/* Potential encode char. */
char * tempEntities = innerHtmlSpecialEntities + i;
for(int j = 0; j < escapeArrayLen; j++)
{
if(strncmp(tempEntities, entityToChars[j].encodedEntity, strlen(entityToChars[j].encodedEntity)) == 0)
{
int index = 0;
strncat(decodedHtmlSpecialChars, innerHtmlSpecialEntities, i);
index = strlen(decodedHtmlSpecialChars);
decodedHtmlSpecialChars[index] = entityToChars[j].decodedChar;
if(strlen(tempEntities) > strlen(entityToChars[j].encodedEntity))
{
/* Not to the end, continue */
char temp[MAX_CONFIG_ITEM_SIZE] = {'\0'};
strcpy(temp, tempEntities + strlen(entityToChars[j].encodedEntity));
memset(innerHtmlSpecialEntities, '\0', MAX_CONFIG_ITEM_SIZE);
strcpy(innerHtmlSpecialEntities, temp);
encodedLen = strlen(innerHtmlSpecialEntities);
i = -1;
}
else
encodedLen = 0;
break;
}
}
}
}
if(encodedLen != 0)
strcat(decodedHtmlSpecialChars, innerHtmlSpecialEntities);
return decodedHtmlSpecialChars;
}
QString UNESC(const QString &txt) {
QStringList bld;
static QChar AMP = '&', SCL = ';';
static QMap<QString, QString> dec = {
{"<", "<"}, {">", ">"}
, {"&", "&"}, {""", R"(")"}, {"'", "'"} };
if(!txt.contains(AMP)) { return txt; }
int bgn = 0, pos = 0;
while((pos = txt.indexOf(AMP, pos)) != -1) {
int end = txt.indexOf(SCL, pos)+1;
QString val = dec[txt.mid(pos, end - pos)];
bld << txt.mid(bgn, pos - bgn);
if(val.isEmpty()) {
end = txt.indexOf(AMP, pos+1);
bld << txt.mid(pos, end - pos);
} else {
bld << val;
}// else // if(val.isEmpty())
bgn = end; pos = end;
}// while((pos = txt.indexOf(AMP, pos)) != -1)
return bld.join(QString());
}// UNESC