Hi all.
This is my first time that I'm trying to use multiple source files. Firstly, here is my full code that compiles and works fine. Sorry for the large program. I was able to work with multiple source files for simple programs, but need help with this particular program.
Code:
// getlinks: get URLs from a forum
#include <curl/curl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define URL_LENGTH 150
struct MemoryStruct {
char *memory;
size_t size;
};
static size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp);
char ** GetLinks(struct MemoryStruct datastruct);
struct MemoryStruct GetInMemory(char *url);
int main(void)
{
curl_global_init(CURL_GLOBAL_ALL);
struct MemoryStruct data;
char *forum_url = "http://cboard.cprogramming.com/c-programming/";
data = GetInMemory(forum_url);
GetLinks(data);
free(data.memory);
return 0;
}
// Get webpage into memory
struct MemoryStruct GetInMemory(char *url)
{
CURL *myhandle;
CURLcode result;
struct MemoryStruct datastruct;
char *URL;
URL = url;
datastruct.memory = malloc(1); // will be grown as needed by realloc
datastruct.size = 0; // no data at this point
if((myhandle = curl_easy_init()) == NULL)
{
perror("curl_easy-init error");
exit(EXIT_FAILURE);
}
if((result = curl_easy_setopt(myhandle, CURLOPT_URL, URL)) != CURLE_OK)
{
perror("CURLOP_URL error");
exit(EXIT_FAILURE);
}
if((result = curl_easy_setopt(myhandle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback)) != CURLE_OK)
{
perror("CURLOPT_WRITEFUNCTION error");
exit(EXIT_FAILURE);
}
if((result = curl_easy_setopt(myhandle, CURLOPT_WRITEDATA, &datastruct)) != CURLE_OK)
{
perror("CURLOPT_WRITEDATA error");
exit(EXIT_FAILURE);
}
if((result = curl_easy_perform(myhandle)) != 0)
{
perror("curl_easy_perform error");
exit(EXIT_FAILURE);
}
curl_easy_cleanup(myhandle);
return datastruct;
}
static size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp)
{
size_t realsize = size * nmemb;
struct MemoryStruct *mem = (struct MemoryStruct *)userp;
mem->memory = realloc(mem->memory, mem->size + realsize + 1);
if (mem->memory == NULL) /* out of memory! */
{
printf("not enough memory (realloc returned NULL)\n");
exit(EXIT_FAILURE);
}
memcpy(&(mem->memory[mem->size]), contents, realsize);
mem->size += realsize;
mem->memory[mem->size] = 0;
return realsize;
}
char ** GetLinks(struct MemoryStruct datastruct)
{
char * temp_string;
char * memory_copy;
char * match; // pointer to search match;
int location; // location of search match;
static char * links[100];
char *search_string = "http://cboard.cprogramming.com/c-programming/";
int ch; // test character
int array_ctr = 0, len_memory_string, len_temp_string, url_buffer_ctr = 0;
len_memory_string = strlen(datastruct.memory);
if((memory_copy = malloc(len_memory_string * sizeof(char) + 1)) == NULL)
{
perror("Memory allocation error #1");
exit(EXIT_FAILURE);
}
strcpy(memory_copy, datastruct.memory);
while((match = strstr(memory_copy, search_string)) != NULL)
{
location = match - memory_copy;
if((links[array_ctr] = malloc(URL_LENGTH * sizeof(char))) == NULL) // allocate memory for pointer to hold URL
{
perror("Memory allocation error #2");
exit(EXIT_FAILURE);
}
while((ch = memory_copy[location]) != '"' && (ch = memory_copy[location]) != '?')
{
links[array_ctr][url_buffer_ctr] = ch;
location++;
url_buffer_ctr++;
}
if((ch = memory_copy[location]) == '"')
{
links[array_ctr][url_buffer_ctr] = '\0';
puts(links[array_ctr]);
array_ctr++; // increment array to accept new URL
url_buffer_ctr = 0; // reset
location++; // move past "
len_temp_string = strlen(memory_copy) - location; // the rest of memory_copy after the "
if((temp_string = malloc(len_temp_string * sizeof(char) + 1)) == NULL)
{
perror("Memory allocation error #3");
exit(EXIT_FAILURE);
}
strcpy(temp_string, &memory_copy[location]);
if((memory_copy = realloc(memory_copy, len_temp_string + 1)) == NULL)
{
perror("Memory allocation error #4");
exit(EXIT_FAILURE);
}
strcpy(memory_copy, temp_string);
continue;
}
if((ch = memory_copy[location]) == '?')
{
url_buffer_ctr = 0; // reset
location++; // move past ?
len_temp_string = strlen(memory_copy) - location;
if((temp_string = realloc(temp_string, len_temp_string + 1)) == NULL)
{
perror("Memory allocation error #5");
exit(EXIT_FAILURE);
}
strcpy(temp_string, &memory_copy[location]);
if((memory_copy = realloc(memory_copy, len_temp_string +1)) == NULL)
{
perror("Memory allocation error #6");
exit(EXIT_FAILURE);
}
strcpy(memory_copy, temp_string);
continue;
}
}
free(memory_copy);
free(temp_string);
return links;
}
I want to put the functions into a separate file, so that I can use them in another program. But I also want to test this program by breaking it down into separate files and building it from the files.
Anyway, here are the 3 files that I have broken the program down into.
main.c
Code:
// getlinks: get URLs from a forum
#include <curl/curl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "links.h"
#define URL_LENGTH 150
static size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp);
char ** GetLinks(struct MemoryStruct datastruct);
struct MemoryStruct GetInMemory(char *url);
int main(void)
{
curl_global_init(CURL_GLOBAL_ALL);
struct MemoryStruct data;
char *forum_url = "http://cboard.cprogramming.com/c-programming/";
data = GetInMemory(forum_url);
GetLinks(data);
free(data.memory);
return 0;
}
links.c
Code:
/* module containing link functions */
#include "links.h"
#include <curl/curl.h>
#include <stdio.h>
struct MemoryStruct {
char *memory;
size_t size;
};
static size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp);
// Get webpage into memory
struct MemoryStruct GetInMemory(char *url)
{
CURL *myhandle;
CURLcode result;
struct MemoryStruct datastruct;
char *URL;
URL = url;
datastruct.memory = malloc(1); // will be grown as needed by realloc
datastruct.size = 0; // no data at this point
if((myhandle = curl_easy_init()) == NULL)
{
perror("curl_easy-init error");
exit(EXIT_FAILURE);
}
if((result = curl_easy_setopt(myhandle, CURLOPT_URL, URL)) != CURLE_OK)
{
perror("CURLOP_URL error");
exit(EXIT_FAILURE);
}
if((result = curl_easy_setopt(myhandle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback)) != CURLE_OK)
{
perror("CURLOPT_WRITEFUNCTION error");
exit(EXIT_FAILURE);
}
if((result = curl_easy_setopt(myhandle, CURLOPT_WRITEDATA, &datastruct)) != CURLE_OK)
{
perror("CURLOPT_WRITEDATA error");
exit(EXIT_FAILURE);
}
if((result = curl_easy_perform(myhandle)) != 0)
{
perror("curl_easy_perform error");
exit(EXIT_FAILURE);
}
curl_easy_cleanup(myhandle);
return datastruct;
}
static size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp)
{
size_t realsize = size * nmemb;
struct MemoryStruct *mem = (struct MemoryStruct *)userp;
mem->memory = realloc(mem->memory, mem->size + realsize + 1);
if (mem->memory == NULL) /* out of memory! */
{
printf("not enough memory (realloc returned NULL)\n");
exit(EXIT_FAILURE);
}
memcpy(&(mem->memory[mem->size]), contents, realsize);
mem->size += realsize;
mem->memory[mem->size] = 0;
return realsize;
}
// Get links from webpage
char ** GetLinks(struct MemoryStruct datastruct)
{
char * temp_string;
char * memory_copy;
char * match; // pointer to search match;
int location; // location of search match;
static char * links[100];
char *search_string = "http://cboard.cprogramming.com/c-programming/";
int ch; // test character
int array_ctr = 0, len_memory_string, len_temp_string, url_buffer_ctr = 0;
len_memory_string = strlen(datastruct.memory);
if((memory_copy = malloc(len_memory_string * sizeof(char) + 1)) == NULL)
{
perror("Memory allocation error #1");
exit(EXIT_FAILURE);
}
strcpy(memory_copy, datastruct.memory);
while((match = strstr(memory_copy, search_string)) != NULL)
{
location = match - memory_copy;
if((links[array_ctr] = malloc(URL_LENGTH * sizeof(char))) == NULL) // allocate memory for pointer to hold URL
{
perror("Memory allocation error #2");
exit(EXIT_FAILURE);
}
while((ch = memory_copy[location]) != '"' && (ch = memory_copy[location]) != '?')
{
links[array_ctr][url_buffer_ctr] = ch;
location++;
url_buffer_ctr++;
}
if((ch = memory_copy[location]) == '"')
{
links[array_ctr][url_buffer_ctr] = '\0';
puts(links[array_ctr]);
array_ctr++; // increment array to accept new URL
url_buffer_ctr = 0; // reset
location++; // move past "
len_temp_string = strlen(memory_copy) - location; // the rest of memory_copy after the "
if((temp_string = malloc(len_temp_string * sizeof(char) + 1)) == NULL)
{
perror("Memory allocation error #3");
exit(EXIT_FAILURE);
}
strcpy(temp_string, &memory_copy[location]);
if((memory_copy = realloc(memory_copy, len_temp_string + 1)) == NULL)
{
perror("Memory allocation error #4");
exit(EXIT_FAILURE);
}
strcpy(memory_copy, temp_string);
continue;
}
if((ch = memory_copy[location]) == '?')
{
url_buffer_ctr = 0; // reset
location++; // move past ?
len_temp_string = strlen(memory_copy) - location;
if((temp_string = realloc(temp_string, len_temp_string + 1)) == NULL)
{
perror("Memory allocation error #5");
exit(EXIT_FAILURE);
}
strcpy(temp_string, &memory_copy[location]);
if((memory_copy = realloc(memory_copy, len_temp_string +1)) == NULL)
{
perror("Memory allocation error #6");
exit(EXIT_FAILURE);
}
strcpy(memory_copy, temp_string);
continue;
}
}
free(memory_copy);
free(temp_string);
return links;
}
links.h
Code:
/* links.h: header file for links.c */
#include <stdio.h>
#ifndef _LINKS_H_
#define _LINKS_H_
static size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp);
char ** GetLinks(struct MemoryStruct datastruct);
struct MemoryStruct GetInMemory(char *url);
#endif // _LINKS_H_
Now when I try to build the program, I get the below error messages, but don't know how to fix them. There were a few more errors before, but I just played around to reduce them. But I don't really know what I am doing.
Thanks in advance.
Code:
links.h|9|warning: 'struct MemoryStruct' declared inside parameter list [enabled by default]|
links.h|9|warning: its scope is only this definition or declaration, which is probably not what you want [enabled by default]|
links.c|71|error: conflicting types for 'GetLinks'|
links.h|9|note: previous declaration of 'GetLinks' was here|
links.c||In function 'GetLinks':|
links.c|92|error: 'URL_LENGTH' undeclared (first use in this function)|
links.c|92|note: each undeclared identifier is reported only once for each function it appears in|
||=== Build finished: 2 errors, 2 warnings (0 minutes, 0 seconds) ===|