ASP/VBScript “Глюки”

У вас есть две большие проблемы с insert. Сначала вы передаете ptr в качестве указателя struct record. Когда это происходит, ваша insert функция получает копию указателя , которая указывает на то же место в памяти, но сама имеет отдельный адрес, очень отличающийся от указателя, переданного из main() , Что это означает, не имеет значения, что вы делаете с копией указателя в insert, эти изменения никогда не будут видны в main(), потому что вы работаете с копией и не возвращаете значение другим способом. Чтобы решить эту проблему, укажите параметр struct record ** и передайте адрес указателя из main().

Следующая самая большая проблема, с которой вы столкнулись в insert, заключается в том, что вы не можете проверить, является ли curptr NULL (как это будет при первом вызове insert), прежде чем вы начнете разыменовывать curptr - вероятно приводя к segfault или другому запуску мельницы Неопределенное поведение.

При создании связанного списка у вас есть два различных условия тестирования, которые вы должны обработать:

  1. Вставляю ли я первый узел? (если так, просто назначьте `* ptr = newptr); и
  2. все другие вставки потребуют от вас итерации, чтобы найти подходящие 2-узлы для вставки ваших данных между ними на основе value из data.

Вы можете обрабатывать оба случая просто:

    rec_t *curptr = *ptr,
        *newptr = malloc (sizeof *newptr);
    if (!newptr) {
        perror ("malloc-newptr");
        return;
    }

    newptr->data = value;
    newptr->nextptr = NULL;

    if (curptr == NULL) {       /* handle new-list case and return */
        *ptr = newptr;
        return;
    }

    if (value < curptr->data) {     /* handle new 1st node */
        newptr->nextptr = curptr;
        *ptr = newptr;
        return;
    }

    /* iterate with curptr until value > curptr->nextptr->data */
    while (curptr->nextptr != NULL && value > curptr->nextptr->data)
        curptr = curptr->nextptr;

    newptr->nextptr = curptr->nextptr;      /* wire new node to next node */
    curptr->nextptr = newptr;               /* wire current to new node */

В любой программе, которую вы пишете, которая выделяет память, вы должны сохранить указатель на начало каждого выделенного блока, чтобы он мог быть освобожден, когда память больше не нужна. Как правило, вы захотите написать функцию listfree, чтобы справиться с этим для вас. Вы могли бы написать что-то простое, например:

void freelist (rec_t *head)
{
    while (head) {
        rec_t *victim = head;
        head = head->nextptr;
        free (victim);
    }
}

( примечание: , как освобождаемый узел сохраняется во временном указателе victim до того, как список переходит к следующему узлу). ). [одна тысяча сто тридцать одна]

В целом, вы можете сделать что-то вроде следующего:

#include <stdio.h>
#include <stdlib.h>

typedef struct record {
    int data;
    struct record *nextptr;
} rec_t;

void insert (rec_t **ptr, int value);
void printList (rec_t *ptr);
void freelist (rec_t *head);

int main (void) {
    rec_t *headptr = NULL;

    for (int i = 0; i < 4; ++i) {
        int data;
        printf("Enter your value: ");
        scanf("%d", &data);
        insert (&headptr, data);
    }
    printList(headptr);
    freelist (headptr);

    return 0;
}

void insert (rec_t **ptr, int value) 
{
    if ( ptr == NULL ) {
        return;  
    } 

    rec_t *curptr = *ptr,
        *newptr = malloc (sizeof *newptr);  /* don't cast the return */
    if (!newptr) {
        perror ("malloc-newptr");
        return;
    }

    newptr->data = value;
    newptr->nextptr = NULL;

    if (curptr == NULL) {       /* handle new-list case and return */
        *ptr = newptr;
        return;
    }

    if (value < curptr->data) {     /* handle new 1st node */
        newptr->nextptr = curptr;
        *ptr = newptr;
        return;
    }

    /* iterate with curptr until value > curptr->nextptr->data */
    while (curptr->nextptr != NULL && value > curptr->nextptr->data)
        curptr = curptr->nextptr;

    newptr->nextptr = curptr->nextptr;      /* wire new node to next node */
    curptr->nextptr = newptr;               /* wire current to new node */
}

void printList(struct record *ptr)
{
    while (ptr != NULL) {
        printf(" %d", ptr->data);
        ptr = ptr->nextptr;
    }
    putchar ('\n');
}

void freelist (rec_t *head)
{
    while (head) {
        rec_t *victim = head;
        head = head->nextptr;
        free (victim);
    }
}

Пример использования / вывода

$ ./bin/lltcmpl
Enter your value: 1
Enter your value: 8
Enter your value: 5
Enter your value: 7
 1 5 7 8

$ ./bin/lltcmpl
Enter your value: 2
Enter your value: 1
Enter your value: 4
Enter your value: 3
 1 2 3 4

Посмотрите вещи и дайте мне знать если у вас есть вопросы.

9
задан AnonJr 22 October 2009 в 04:09
поделиться

9 ответов

Повторитесь после меня: Все хорошие программисты VB используют Option Explicit

Это сохранит Вас от случайного объявления новой переменной и использования его - таким образом отбрасывающий независимо от того, что Вы делаете.

Кроме того, это зависит от того, что Вы делаете.

10
ответ дан 4 December 2019 в 07:15
поделиться

Остерегайтесь каждый раз, когда Вы видите следующую строку:

On Error Resume Next

Это было бы моей осторожностью в использовании классического ASP.

8
ответ дан 4 December 2019 в 07:15
поделиться

Условные выражения время от времени немного неинтуитивны.

Например, при контакте с Nulls: Хотя True и Null не равны, следующее выражение будет действовать как False. В этом случае хорошо проверить на Null явно использование IsNull.

valueIsTrue = True
valueIsNull = Null
If valueIsTrue <> valueIsNull Then ...

Кроме того, в отличие от некоторых других языков, оценены все части условия, даже если первая часть False. Например, следующий пример возвратил бы ошибку если myObject были Nothing:

If Not IsNothing(myObject) And myObject.IsValid() Then ...

Решение состоит в том, чтобы разделить вложенное использование условий Ifs или некоторые другие средства:

If Not IsNothing(myObject) Then
    If myObject.IsValid() Then
        ...
4
ответ дан 4 December 2019 в 07:15
поделиться

Общий Глюк, когда использование HTML-форм является несоответствием между CharSet страницы формы и CodePage страницы получения.

Типичный пример - то, где страница Form устанавливает свой CodePage на 65 001 и ответ CharSet к UTF-8. Это вызывает любые значения, ввел в форму, которая будет отправлена назад с помощью кодировки UTF-8. Страница получения уезжает, ее CodePage устанавливают Систему кодовая страница OEM такой 1252.

Противостоите интуитивно использованию ASP Ответ. CodePage, чтобы определить, как символы в сообщении формы должны быть интерпретированы, следовательно кодировка UTF-8, ошибочно принят как набор ot 1 252 символа, повреждающие вход.

Иногда это идет необнаруженное, потому что страница отвечает, устанавливает его Reponse. CharSet к UTF-8, но оставляет свой CodePage без изменений. Результат пользователю кажется хорошим, но данные ввели в базу данных, повреждено.

Моей рекомендацией является Сохранение как UTF-8, используйте @codepage = 65001 на всех страницах и всегда устанавливайте Ответ. CharSet к UTF-8. Это покрывает все.

3
ответ дан 4 December 2019 в 07:15
поделиться

VBScript имеет nastly способ позволить Вам назвать нижние индексы с круглой скобкой, если у Вас только есть 1 параметр. Однако, если та парамать передается ссылкой, возвращаемое значение не выходит при использовании круглой скобки:

<% OPTION EXPLICIT %>
<%

sub MakeLonger(byref something)
    something = "hello " & something 
end sub

dim msg
msg = "World"

MakeLonger(msg)
response.write msg
response.write "<br />"

MakeLonger msg
response.write msg

%>

Вывод:

World 
hello World
3
ответ дан 4 December 2019 в 07:15
поделиться

Удостоверьтесь, что Вы используете Set для ссылок на объект:

 Dim rs : Set rs = CreateObject("ADODB.Recordset");

Если Вы не сделаете то Вы или получите недопустимую ссылку на переменную или свойство по умолчанию

 Dim field      : Set field  = rs(0)
 Dim fieldValue : fieldValue = rs(0) 'Same as field.Value
2
ответ дан 4 December 2019 в 07:15
поделиться

Можно не учесть круглую скобку, когда передающие аргументы функциям, но только если вызов функции является единственным выражением в операторе:

 DoSomething withThisArgument
 Dim result : result = DoSomething(withThisArgument)
 result = DoSomething withThisArgument 'SYNTAX ERROR
1
ответ дан 4 December 2019 в 07:15
поделиться

Выделение автоматической переменной является, вероятно, одним из самых больших глюков.

Dim varA, varB

varA = varA + varV

Ой! Что varV Вы спрашиваете? Хорошо.. Я просто ввел B с опечаткой для V, и все все еще работает отлично.. это должно быть хорошей вещью!

Разве кроме того, почему varB не, добавляется к варе?? Это должно быть ошибкой Microsoft!

0
ответ дан 4 December 2019 в 07:15
поделиться

классический ASP имеет много глюков, если бы Вы никогда не работали с ним то :) я рекомендовал бы взглянуть на ajaxed библиотеку, которая является все еще сохраняемой классической библиотекой asp. Это помогает Вам избавиться от наиболее распространенных глюков при контакте с приложениями прежней версии.

0
ответ дан 4 December 2019 в 07:15
поделиться
Другие вопросы по тегам:

Похожие вопросы: