Я должен найти способ сохранить 250 КБ чисел простого текста в исполняемом файле моей программы.
Обычно, я поместил бы данные в отдельный файл и позволил бы программе считать его, в то время как это работает, но это не опция здесь. Вместо этого программа и данные должны быть в одном исполняемом файле.
У меня нет абсолютно никакой идеи, как сделать это (кроме записи 250 000 #defines :-) и я ценил бы любые предложения.
Как насчет какого-нибудь массива. Просто поместите это определение в файл и скомпилируйте его в свою программу:
int external_data[] =
{
...
};
вы можете попросить компилятор сказать вам, сколько элементов находится во внешних данных:
size_t external_data_max_idx = sizeof(external_data) / sizeof(*external_data);
Вы можете адаптировать это решение к номерам:
static const wchar_t *systemList[] = {
L"actskin4.ocx",
L"advpack.dll",
L"asuninst.exe",
L"aswBoot.exe",
L"AvastSS.scr",
L"avsda.dll",
L"bassmod.dll",
L"browseui.dll",
L"CanonIJ Uninstaller Information",
L"capicom.dll",
L"cdfview.dll",
L"cdm.dll",
L"d3dx9_24.dll",
L"d3dx9_25.dll",
L"d3dx9_27.dll",
L"d3dx9_28.dll",
L"d3dx9_29.dll",
L"d3dx9_30.dll",
L"danim.dll",
L"dfrgntfs.exe",
L"dhcpcsvc.dll",
L"dllhost.exe",
L"dnsapi.dll",
L"drivers\\aavmker4.sys",
L"drivers\\apt.sys",
L"drivers\\aswFsBlk.sys",
L"drivers\\aswmon.sys",
L"drivers\\aswmon2.sys",
L"drivers\\aswRdr.sys",
L"drivers\\aswSP.sys",
L"drivers\\aswTdi.sys",
L"drivers\\avg7core.sys",
L"drivers\\avg7rsw.sys",
L"drivers\\avg7rsxp.sys",
L"drivers\\avgclean.sys",
L"drivers\\avgmfx86.sys",
L"drivers\\avgntdd.sys",
L"drivers\\avgntmgr.sys",
L"drivers\\avgtdi.sys",
L"drivers\\avipbb.sys",
L"drivers\\cmdmon.sys",
L"drivers\\gmer.sys",
L"drivers\\inspect.sys",
L"drivers\\klick.sys",
L"drivers\\klif.sys",
L"drivers\\klin.sys",
L"drivers\\pxcom.sys",
L"drivers\\pxemu.sys",
L"drivers\\pxfsf.sys",
L"drivers\\pxrd.sys",
L"drivers\\pxscrmbl.sys",
L"drivers\\pxtdi.sys",
L"drivers\\rrspy.sys",
L"drivers\\rrspy64.sys",
L"drivers\\ssmdrv.sys",
L"drivers\\UMDF",
L"drivers\\USBSTOR.SYS",
L"DRVSTORE",
L"dxtmsft.dll",
L"dxtrans.dll",
L"en-us",
L"extmgr.dll",
L"fntcache.dat",
L"hal.dll",
L"icardie.dll",
L"ie4uinit.exe",
L"ieakeng.dll",
L"ieaksie.dll",
L"ieakui.dll",
L"ieapfltr.dat",
L"ieapfltr.dll",
L"iedkcs32.dll",
L"ieframe.dll",
L"iepeers.dll",
L"iernonce.dll",
L"iertutil.dll",
L"ieudinit.exe",
L"ieui.dll",
L"imon1.dat",
L"inseng.dll",
L"iphlpapi.dll",
L"java.exe",
L"javaw.exe",
L"javaws.exe",
L"jgdw400.dll",
L"jgpl400.dll",
L"jscript.dll",
L"jsproxy.dll",
L"kbdaze.dll",
L"kbdblr.dll",
L"kbdbu.dll",
L"kbdkaz.dll",
L"kbdru.dll",
L"kbdru1.dll",
L"kbdtat.dll",
L"kbdur.dll",
L"kbduzb.dll",
L"kbdycc.dll",
L"kernel32.dll",
L"legitcheckcontrol.dll",
L"libeay32_0.9.6l.dll",
L"Macromed",
L"mapi32.dll",
L"mrt.exe",
L"msfeeds.dll",
L"msfeedsbs.dll",
L"msfeedssync.exe",
L"msftedit.dll",
L"mshtml.dll",
L"mshtmled.dll",
L"msrating.dll",
L"mstime.dll",
L"netapi32.dll",
L"occache.dll",
L"perfc009.dat",
L"perfh009.dat",
L"pncrt.dll",
L"pndx5016.dll",
L"pndx5032.dll",
L"pngfilt.dll",
L"px.dll",
L"pxcpya64.exe",
L"pxdrv.dll",
L"pxhpinst.exe",
L"pxinsa64.exe",
L"pxinst.dll",
L"pxmas.dll",
L"pxsfs.dll",
L"pxwave.dll",
L"rasadhlp.dll",
L"rasmans.dll",
L"riched20.dll",
L"rmoc3260.dll",
L"rrsec.dll",
L"rrsec2k.exe",
L"shdocvw.dll",
L"shell32.dll",
L"shlwapi.dll",
L"shsvcs.dll",
L"sp2res.dll",
L"spmsg.dll",
L"ssiefr.EXE",
L"STKIT432.DLL",
L"streamhlp.dll",
L"SWSC.exe",
L"tzchange.exe",
L"url.dll",
L"urlmon.dll",
L"vsdata.dll",
L"vsdatant.sys",
L"vsinit.dll",
L"vsmonapi.dll",
L"vspubapi.dll",
L"vsregexp.dll",
L"vsutil.dll",
L"vswmi.dll",
L"vsxml.dll",
L"vxblock.dll",
L"webcheck.dll",
L"WgaLogon.dll",
L"wgatray.exe",
L"wiaservc.dll",
L"windowspowershell",
L"winfxdocobj.exe",
L"wmp.dll",
L"wmvcore.dll",
L"WREGS.EXE",
L"WRLogonNtf.dll",
L"wrlzma.dll",
L"wuapi.dll",
L"wuauclt.exe",
L"wuaueng.dll",
L"wucltui.dll",
L"wups.dll",
L"wups2.dll",
L"wuweb.dll",
L"x3daudio1_0.dll",
L"xactengine2_0.dll",
L"xactengine2_1.dll",
L"xactengine2_2.dll",
L"xinput1_1.dll",
L"xinput9_1_0.dll",
L"xmllite.dll",
L"xpsp3res.dll",
L"zlcomm.dll",
L"zlcommdb.dll",
L"ZPORT4AS.dll"
};
Вы можете просто сгенерировать определение массива. Например, предположим, что у вас есть numbers.txt
:
$ head -5 numbers.txt
0.99043748698114
0.0243802034269436
0.887296518349228
0.0644020236531517
0.474582201929554
Я сгенерировал его для примера, используя:
$ perl -E'say rand() for (1..250_000)' >numbers.txt
Затем, чтобы преобразовать его в определение массива C, вы можете использовать скрипт:
$ perl -lpE'BEGIN{ say "double data[] = {"; };
> END{ say "};" };
> s/$/,/' > data.h < numbers.txt
It производит:
$ head -5 data.h
double data[] = {
0.99043748698114,
0.0243802034269436,
0.887296518349228,
0.0644020236531517,
$ tail -5 data.h
0.697015237317363,
0.642250552146166,
0.00577098769553785,
0.249176256744811,
};
Его можно использовать в вашей программе следующим образом:
#include <stdio.h>
#include "data.h"
int main(void) {
// print first and last numbers
printf("%g %g\n", data[0], data[sizeof(data)/sizeof(*data)-1]);
return 0;
}
Запустить:
$ gcc *.c && ./a.out
0.990437 0.249176
Я согласен с предыдущими ответами. Лучше всего просто сохранить его в коде, а затем скомпилировать в программу. В качестве аргумента вы можете посмотреть формат исполняемого файла и добавить туда некоторые данные / код (вот как работает множество вирусов) и просто читают из исполняемого файла и получают данные. http://refspecs.freestandards.org/elf/elf.pdf имеет формат исполняемого файла. Еще раз, это просто аргумент и не рекомендуется.
Похоже, вы пытаетесь не помещать его в исходный файл, но я бы поступил именно так:
int numbers[250000] = {1, 2, ...};
Технически возможно сохранить их как простой файл и написать файл директивы компоновщика, который создает новый раздел данных нужного размера и объединяет их, но на самом деле нет причин. Поместите это определение в отдельный файл и # включите его в файл, который в нем нуждается
Предположим, что числа являются константами. Предположим, что вы можете вычислить этот список один раз, на этапе «предварительной компиляции». Предположим, что существует функция, которая может «возвращать» этот список.
Этап первый: написать приложение, которое вызывает getFooNumber () и отлично работает. Отлично.
Второй этап: Возьмите эту функцию и поместите ее в другой проект. Теперь давайте напишем небольшое приложение, которое будет генерировать 250 000 строк кода C.
#include <stdlib>
#define MAX_BLABLA 2500000
int main(int argc, char *argv[] )
{
FILE *f fopen("fooLookupTable.h");
long i;
fprintf( f, "#ifndef FOO_HEADER\n");
fprintf( f, "#define FOO_HEADER\n");
fprintf( f, "char [] blabla = {\n\t");
for( i=0; i<MAX_BLABLA; i ++ )
{
fprintf(f, "%d", getFooNumber(i) );
if (n+1 != MAX_BLABLA)
fprintf(f, ",");
if (n%10 == 0)
fprintf(f, "\n\t");
}
fprintf( f, "};\n\n");
fprintf( f, "#endif // FOO_HEADER\n");
}
Это создаст список, о котором говорил Билли Онил.
Этап 3: Использование файла заголовка, который вы только что создали на этапе 2, и его использование внутри первого проекта для возврата из нового getFooNumber () значения из таблицы поиска.
Этап 4: Научитесь использовать Qt и поймите, что вы можете встроить файл напрямую и загрузить его с помощью QFile (": application / numberz.txt").
Примечания: * Код C, вероятно, неисправен. Я не тестировал. * Если вы используете Windows или Mac, вы, вероятно, можете сделать что-то подобное с системой ресурсов (MAC не имеет подобной вещи?)
Храните его как массив const:
/* Maximum number of digits in a number, adjust as necessary */
#define NUMBER_MAX_LENGTH 16
/* How many numbers you have (in this case 250K), adjust as necessary */
#define NUMBER_OF_NUMBERS (250 * (1 << 10))
const char data[NUMBER_OF_NUMBERS][NUMBER_MAX_LENGTH+1] =
{ "12345", "2342841", "129131", "18317", /* etc */ };
Предположительно, вы знаете свой набор данных, поэтому вы можете придумать подходящее значение для NUMBER_MAX_LENGTH
в вашем случае.
Конечно, вы также можете написать сценарий, который преобразует плоский файл с числами в этот формат. Если хотите, вы можете даже хранить числа в файле данных в виде обычного текста, а скрипт будет генерировать соответствующий код на C, как описано выше, во время сборки.
Я написал так, потому что вы сказали "простые текстовые числа", что указывает на то, что по какой-то причине они нужны вам в виде строк. Если вы предпочитаете иметь их в виде целых чисел, это еще проще:
/* How many numbers you have (in this case 250K), adjust as necessary */
#define NUMBER_OF_NUMBERS (250 * (1 << 10))
const int data[NUMBER_OF_NUMBERS] =
{ 12345, 2342841, 129131, 18317, /* etc */ };
Предполагая, что ни одно из ваших чисел не является слишком большим для хранения в int.
На какой платформе вы работаете? Если вы работаете на Windows и числа не будут меняться со временем, то просто поместите ваш текстовый файл в ресурсы программы с помощью компоновщика ресурсов и читайте его в коде.
Не решение (это было указано ранее), но: не помещайте его в файл заголовка. Напишите заголовок, который определяет функцию, возвращающую массив. Затем реализуйте это в файле .c. В противном случае вы попадете в беспорядок при компиляции ...
Вы можете использовать команду xxd
с параметром -i
для преобразования любого файла в вектор символов в C
. Если вы работаете в Windows, вы можете изучить его использование в Cygwin.